首页 > 解决方案 > SwiftUI 匹配几何效果崩溃或带有惰性网格的错误?

问题描述

这是一个基本的英雄动画设置,似乎 90% 的时间都有效。但随机动画开始无法正确动画,偶尔会导致应用程序崩溃。我尽可能简单地尝试缩小问题范围。在设备和模拟器上进行了数小时的测试后,我无法弄清楚为什么动画有时无法正确地为网格中的某些项目设置动画,并且无法找出崩溃的原因。

没有错误代码被抛出,除了“匹配几何组中的多个插入视图具有 isSource:true,结果未定义。” 但是,如果我设置源动画也会中断,没有源设置动画会正确播放..直到它没有。

需要多次单击网格项目,直到最终您会看到动画无法正确飞入甚至根本没有出现,尝试不同的网格项目并且它可以正常工作,回到不正确的项目并且它可能会或可能不会飞正确地,继续前进,最终它会崩溃。

我想知道我是否不了解 SwiftUI,或者这是一个错误?

网格:

struct Prototype_RecipeGrid: View {

@Namespace var namespace
@State private var selectedRecipe: Int? = nil

var body: some View {
    
    
    ZStack {
        
        
        NavigationView {
            ScrollView {
                LazyVGrid(columns: [GridItem()], spacing: 20) {
                    ForEach(0 ..< 8) { index in
                        
                        Prototype_RecipeCard(index: index, namespace: namespace)
                            .onTapGesture { open(index) }

                    }
                }
                .padding(.horizontal)
            }
            .navigationTitle("Recipes")
        }
        .zIndex(1)
    
        
        if selectedRecipe != nil {
            Prototype_RecipeDetail(close: close, index: selectedRecipe!, namespace: namespace)
                .onTapGesture { close() }
                .zIndex(3)
        }
    }
}

private func open(_ index: Int) {
    withAnimation(.spring()) {
        selectedRecipe = index
    }
}

private func close() {
    withAnimation(.linear(duration: 0.25)) {
        selectedRecipe = nil
    }
}

}

格子卡:

struct Prototype_RecipeCard: View {

let index: Int
let namespace: Namespace.ID

var body: some View {
    Color.clear.overlay(
    
        GeometryReader { geo in
            ZStack(alignment: .topLeading) {
                Image("047224BD-6F84-4990-9E4D-B46E425FBC5D")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .matchedGeometryEffect(id: "img\(index)", in: namespace)
                    .frame(height: 180)
                    .frame(width: geo.size.width)
                
                Prototype_RecipeTitle()
                    .matchedGeometryEffect(id: "title\(index)", in: namespace)
            }
        }
    )
    .matchedGeometryEffect(id: "detail\(index)", in: namespace)
    .clipShape(RoundedRectangle(cornerRadius: 25.0, style: .continuous))
    //.transition(.move(edge: .bottom))
    .shadow(radius: 10)
    .frame(height: 180)
}

}

英雄放大卡:

struct Prototype_RecipeDetail: View {
var close: () -> Void

let index: Int
let namespace: Namespace.ID

var body: some View {

    Color.clear.overlay(
        GeometryReader { geo in
            ScrollView(showsIndicators: false) {
                VStack {
                    ZStack(alignment: .bottomLeading) {
                        Image("047224BD-6F84-4990-9E4D-B46E425FBC5D")
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .matchedGeometryEffect(id: "img\(index)", in: namespace)
                            .frame(height: 375)
                            .frame(width: geo.size.width)

                        Prototype_RecipeTitle()
                            .matchedGeometryEffect(id: "title\(index)", in: namespace)
                    }

                    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed risus sollicitudin, placerat massa non, facilisis tellus. Ut lorem est, sodales ut diam in, imperdiet tempor mauris. Donec sit amet elit dapibus, scelerisque tellus a, malesuada eros. Phasellus rutrum, turpis vel tempor placerat, nulla est blandit justo, sit amet faucibus libero nibh eu nisl. Curabitur quis mauris purus. Maecenas at laoreet tortor. Duis pretium auctor pulvinar. Nulla posuere risus nec sapien ornare sagittis. Nunc molestie aliquam blandit. Curabitur ut elementum felis, sit amet bibendum justo. Integer elementum et justo a bibendum. Vestibulum bibendum purus eu arcu scelerisque tempus. Donec interdum auctor neque vel tincidunt. Nulla facilisi. Quisque ut semper felis, vitae vestibulum ante. Ut et dictum tellus, ultricies condimentum orci. Aenean gravida massa vitae massa finibus suscipit. Duis sit amet ex facilisis, viverra purus non, gravida ante. Ut urna dui, consectetur ac tempus et, accumsan non est. Suspendisse sed volutpat metus. Maecenas ac neque nisl. In a efficitur purus. Curabitur ex est, vehicula vitae ipsum pulvinar, aliquet elementum purus. Mauris rhoncus maximus leo, cursus sodales elit interdum vitae. Ut et felis et purus pulvinar efficitur. Nullam pellentesque molestie nisi at rhoncus. Vestibulum sed urna non erat aliquet volutpat vel sit amet quam. Ut neque lorem, auctor a ipsum eget, volutpat consectetur urna. Phasellus eleifend maximus libero, et maximus velit lobortis non.")
                        .padding(.horizontal)
                    
                    Spacer()
                }
                .background(Color(.systemBackground))
                .clipShape(RoundedRectangle(cornerRadius: 25.0, style: .continuous))
                .onTapGesture { close() }
            }
        }
    )
    .clipShape(RoundedRectangle(cornerRadius: 25.0, style: .continuous))
    .matchedGeometryEffect(id: "detail\(index)", in: namespace)
    //.transition(.move(edge: .bottom))
    //.frame(height: 750)
    .edgesIgnoringSafeArea(.all)


}

}

标签: swiftswiftui

解决方案


推荐阅读