Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SwiftUI中正确使用动态成员绑定?_Swiftui_Swiftui State - Fatal编程技术网

如何在SwiftUI中正确使用动态成员绑定?

如何在SwiftUI中正确使用动态成员绑定?,swiftui,swiftui-state,Swiftui,Swiftui State,我试图使用SwiftUI的绑定成员来自@Binding变量(通过其对@dynamicMemberLookup的支持),但即使使用一个简单的示例,我也可以重新创建多个问题。我最好的猜测是我没有正确地使用它,但网上的文档和示例会给出相反的建议 主要问题(可在Catalina、Big Sur和iPadOS 13和14上重现)是在视图打开时删除项会触发崩溃,并导致索引超出范围错误 Fatal error: Index out of range: file /AppleInternal/BuildRoot

我试图使用SwiftUI的
绑定
成员来自
@Binding
变量(通过其对
@dynamicMemberLookup
的支持),但即使使用一个简单的示例,我也可以重新创建多个问题。我最好的猜测是我没有正确地使用它,但网上的文档和示例会给出相反的建议

主要问题(可在Catalina、Big Sur和iPadOS 13和14上重现)是在视图打开时删除项会触发崩溃,并导致索引超出范围错误

Fatal error: Index out of range: file /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.8.25.8/swift/stdlib/public/core/ContiguousArrayBuffer.swift, line 444
第二个问题出现在Catalina的文本字段中,试图编辑文本会隐藏左/导航视图。(在Big Sur上,编辑文本会隐藏右视图/详细视图,我认为由于导航视图的改进,这是同一问题的不同表现形式。)

struct子级:可识别、可散列{
var id=UUID()
变量栏:String=“Text”
func散列(放入散列程序:inout散列程序){
self.id.hash(放入:&hasher)
}
}
结构子视图:视图{
让孩子:孩子
var body:一些观点{
文本(child.bar)
}
}
结构子编辑器:视图{
@绑定变量child:child
var body:一些观点{
文本字段(“文本”,文本:self.$child.bar)
}
}
结构ContentView:View{
@状态变量子项:[Child]=[]
func绑定(用于子对象:子对象)->绑定{
guard let it=children.firstIndex(of:child)else{
法塔莱罗()
}
返回$children[it]
}
var plusButton:按钮{
返回按钮(操作:{
self.children.append(Child())
}) {
图像(系统名称:“plus”)
}
}
func父列表(u内容:()->内容)->一些视图{
#如果操作系统(macOS)
退货清单(内容:content)
.工具栏{
工具栏项{
自选按钮
}
}
//10.15的取消注释
//返回列表{
//自选按钮
//内容()
//        }
#elseif操作系统(iOS)
退货清单(内容:content)
.navigationBarItems(尾部:self.plusButton)
#恩迪夫
}
var body:一些观点{
导航视图{
父母名单{
ForEach(儿童){child in
NavigationLink(目标:ChildEditor(子:self.binding(for:child))){
子视图(子:子)
}
}
.onDelete{中的偏移量
self.children.remove(原子偏移:偏移)
}
}
}
}
}
我的基本假设是,
Binding
本质上存储一个指针,因此删除指针将变得无效并触发崩溃,编辑文本字段将触发父视图的视图更新,从而使当前内容无效(Big Sur有时会抱怨状态变量在视图更新过程中被修改,即使它只正确地用于
文本字段的init
)。但是,更改为使用类类型和
@ObservedObject
/
@EnvironmentObject
(或
@StateObject
)会延迟崩溃(在Catalina和iPadOS 13/14上)到何时采取任何其他导航操作或没有任何影响(在Big Sur上)。如果删除操作失败,则使用
导航链接中的
标记
选项关闭视图


第一个问题是:我做错了什么?如果答案是“一切”,如何管理顶级视图中的数据数组并为嵌套子视图创建成员绑定?

使用-所有这些情况都已经描述过了我看了一下,有几个解决方案确实与我尝试的方法相匹配,但我仍然会遇到崩溃。我看不出有什么不同。使用-所有这些情况都已经取消scribedI确实看了一眼,有几个解决方案确实符合我正在尝试的,但我仍然遇到了崩溃。我看不出有什么不同。
struct Child: Identifiable, Hashable {
    var id = UUID()
    var bar: String = "Text"

    func hash(into hasher: inout Hasher) {
        self.id.hash(into: &hasher)
    }
}

struct ChildView: View {
    let child: Child

    var body: some View {
        Text(child.bar)
    }
}

struct ChildEditor: View {
    @Binding var child: Child

    var body: some View {
        TextField("Text", text: self.$child.bar)
    }
}

struct ContentView: View {
    @State var children: [Child] = []

    func binding(for child: Child) -> Binding<Child> {
        guard let it = children.firstIndex(of: child) else {
            fatalError()
        }
        return $children[it]
    }

    var plusButton: Button<Image> {
        return Button(action: {
            self.children.append(Child())
        }) {
            Image(systemName: "plus")
        }
    }

    func ParentList<Content: View>(_ content: () -> Content) -> some View {
        #if os(macOS)
        return List(content: content)
            .toolbar {
                ToolbarItem {
                    self.plusButton
                }
            }
        // uncomment for 10.15
//        return List {
//            self.plusButton
//            content()
//        }
        #elseif os(iOS)
        return List(content: content)
            .navigationBarItems(trailing: self.plusButton)
        #endif
    }

    var body: some View {
        NavigationView {
            ParentList {
                ForEach(children) { child in
                    NavigationLink(destination: ChildEditor(child: self.binding(for: child))) {
                        ChildView(child: child)
                    }
                }
                .onDelete { offsets in
                    self.children.remove(atOffsets: offsets)
                }
            }
        }
    }
}