SwiftUI 匹配几何 + LazyVStack = 崩溃 [英] SwiftUI matchedGeometry + LazyVStack = crash

查看:36
本文介绍了SwiftUI 匹配几何 + LazyVStack = 崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了几个小时来构建这个例子,我不确定我是否做错了什么,或者在使用 matchedGeometry + LazyVStack.

It took me hours to construct this example, and I'm not sure if I am doing something wrong or there is a bug crashing the app when using matchedGeometry + LazyVStack.

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

In the video below the app crashed when I click on third rectangle (which was not visible when the app started). Crash disappears if I replace LazyVStack with VStack, but obviously I want to lazy load my things.

Xcode 版本:版本 12.0.1 (12A7300)

Xcode version: Version 12.0.1 (12A7300)

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
                        }
                    }
            }
        }
    }
}

推荐答案

问题是你破坏了 ScrollView 破坏了匹配的布局.

The problem is that you destroy ScrollView breaking matched layout.

这是固定变体.使用 Xcode 12/iOS 14 测试

Here is fixed variant. Tested with Xcode 12 / iOS 14

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
                        }
                    }
                        }
            }
        }
    }
}

这篇关于SwiftUI 匹配几何 + LazyVStack = 崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆