Animation 迅捷匹配几何测量+;懒散=崩溃

Animation 迅捷匹配几何测量+;懒散=崩溃,animation,swiftui,Animation,Swiftui,构建这个示例花了我几个小时,我不确定使用matchedGeometry+LazyVStack时是做错了什么,还是有bug使应用程序崩溃 在下面的视频中,当我单击第三个矩形时,应用程序崩溃(应用程序启动时不可见)。如果我将LazyVStack替换为VStack,崩溃就会消失,但显然我想延迟加载我的东西 Xcode版本:12.0.1版(12A7300) struct ContentView:View{ @名称空间变量名称空间 @选择的状态变量:Int? var body:一些观点{ ZStack

构建这个示例花了我几个小时,我不确定使用
matchedGeometry
+
LazyVStack
时是做错了什么,还是有bug使应用程序崩溃

在下面的视频中,当我单击第三个矩形时,应用程序崩溃(应用程序启动时不可见)。如果我将
LazyVStack
替换为
VStack
,崩溃就会消失,但显然我想延迟加载我的东西

Xcode版本:12.0.1版(12A7300)

struct ContentView:View{
@名称空间变量名称空间
@选择的状态变量:Int?
var body:一些观点{
ZStack{
VStack{
文本(“冷矩形”)
如果选择==nil{
滚动视图(.vertical,showsIndicators:false){
BoxList(名称空间:名称空间,选定:$selected)
}
}
}
如果let id=选中{
矩形()
.foregroundColor(.red)
.matchedGeometryEffect(id:id,in:namespace)
.ontapsigne{
动画片{
所选=零
}
}
}
}
}
}
结构框列表:视图{
让命名空间:namespace.ID
@选择绑定变量:Int?
var body:一些观点{
懒散的{

ForEach(0..问题是您破坏了
ScrollView
破坏了匹配的布局

这是一个固定的变体。使用Xcode 12/iOS 14进行测试

struct ContentView:View{
@名称空间变量名称空间
@选择的状态变量:Int?
var body:一些观点{
ZStack{
VStack{
文本(“冷矩形”)
滚动视图(.vertical,showsIndicators:false){
BoxList(名称空间:名称空间,选定:$selected)
}.不透明度(所选==nil?1:0)

}//谢谢您的回复,但是为什么销毁视图会成为一个问题呢?当然,人们经常希望在条件下显示/隐藏视图。似乎更自然的方法是使用if/else来显示视图,而不是使用不透明性?这不是一般的显示/隐藏,而它,
if
实际上是添加/删除视图,但问题是关于
MatchedGeometryffect
,它要求两个具有相同id的匹配视图都存在,但通过删除ScrollView,您会破坏一组匹配的成对视图。这就是原因。
struct ContentView: View {
    @Namespace var namespace
    @State var selected: Int?


    var body: some View {
        ZStack {
            VStack { 
                Text("Cool rectangles")
                
                if selected == nil {
                    ScrollView(.vertical, showsIndicators: false) {
                        BoxList(namespace: namespace, selected: $selected)
                    }
                }
            }
            
            if let id = selected {
                Rectangle()
                    .foregroundColor(.red)
                    .matchedGeometryEffect(id: id, in: namespace)
                    .onTapGesture {
                        withAnimation{
                            selected = nil
                        }
                    }

            }

        }
    }
}

struct BoxList: View {
    let namespace: Namespace.ID
    @Binding var selected: Int?
    
    var body: some View {
        LazyVStack {
            ForEach(0..<10){ item in
                Rectangle()
                    .matchedGeometryEffect(id: item, in: namespace)
                    .frame(width: 200, height: 200)
                    .onTapGesture {
                        withAnimation {
                            selected = item
                        }
                    }
            }
        }
    }
}
struct ContentView: View {
    @Namespace var namespace
    @State var selected: Int?


    var body: some View {
        ZStack {
            VStack {
                Text("Cool rectangles")
                
                  ScrollView(.vertical, showsIndicators: false) {
                        BoxList(namespace: namespace, selected: $selected)
                  }.opacity(selected == nil ? 1 : 0)
            } // << or place here opacity modifier here
            
            if let id = selected {
                Rectangle()
                    .foregroundColor(.red)
                    .matchedGeometryEffect(id: id, in: namespace)
                    .onTapGesture {
                        withAnimation{
                            selected = nil
                        }
                    }

            }

        }
    }
}

struct BoxList: View {
    let namespace: Namespace.ID
    @Binding var selected: Int?
    
    var body: some View {
        LazyVStack {
            ForEach(0..<10){ item in
                    if item == selected {
                Color.clear     // placeholder to avoid duplicate match id run-time warning
                    .frame(width: 200, height: 200)
                    } else {
                Rectangle()
                    .matchedGeometryEffect(id: item, in: namespace)
                    .frame(width: 200, height: 200)
                    .onTapGesture {
                        withAnimation {
                            selected = item
                        }
                    }
                        }
            }
        }
    }
}