Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.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
Asynchronous SwiftUI在多个视图上使用环境对象,导致导航问题_Asynchronous_Swiftui_Navigationview_Environmentobject_Viewroot - Fatal编程技术网

Asynchronous SwiftUI在多个视图上使用环境对象,导致导航问题

Asynchronous SwiftUI在多个视图上使用环境对象,导致导航问题,asynchronous,swiftui,navigationview,environmentobject,viewroot,Asynchronous,Swiftui,Navigationview,Environmentobject,Viewroot,不知道我是否滥用了环境对象的概念,但在使用发布延迟异步值的环境对象时遇到了问题。一个视图会导航到下一个视图,但随后会更新“根”视图,结果会导致“回音”,或者即使这是一个导航问题。当使用导航之间的转换时,问题变得更加明显。 是否有正确的使用模式来避免这种情况?或者其他解决办法 任何指导都将不胜感激 附上一个浓缩样品来说明这个问题 Xcode 12.4 ios 14.1 final class SetColor: ObservableObject { @Published var async

不知道我是否滥用了环境对象的概念,但在使用发布延迟异步值的环境对象时遇到了问题。一个视图会导航到下一个视图,但随后会更新“根”视图,结果会导致“回音”,或者即使这是一个导航问题。当使用导航之间的转换时,问题变得更加明显。 是否有正确的使用模式来避免这种情况?或者其他解决办法

任何指导都将不胜感激

附上一个浓缩样品来说明这个问题

Xcode 12.4 ios 14.1

final class SetColor: ObservableObject {
    @Published var asyncVal: Bool = false
    
    func flipIt() {
        DispatchQueue.main.asyncAfter(deadline: .now()+0.5, execute: {self.asyncVal.toggle()})
    }
}

struct HomeView: View {
    @StateObject var setCol: SetColor = SetColor()
    @State private var navActive: Bool = false
    var body: some View {
        NavigationView {
            ZStack {
                Color(setCol.asyncVal ? .blue : .purple)
                Button(action: {
                    setCol.flipIt()
                    navActive.toggle()
                }, label: {
                    Text("Change and Move")
                })
                .navigationTitle("Home")
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        NavigationLink(destination: NavChild1().environmentObject(setCol),isActive: $navActive, label: { Text("GoTo 1 >") })
                    }
                }
            }
        }
    }
}

struct NavChild1: View {
    @EnvironmentObject var setCol: SetColor
    @State private var navActive: Bool = false
    var body: some View {
        ZStack {
            Color(setCol.asyncVal ? .yellow : .orange)
            Button(action: {
                setCol.flipIt()
                navActive.toggle()
            }, label: {
                Text("Change and Move")
            })
            .navigationTitle("Nav 1")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    NavigationLink(destination: NavChild2().environmentObject(setCol),isActive: $navActive, label: { Text("GoTo 2 >") })
                }
            }
        }
    }
}

struct NavChild2: View {
    @EnvironmentObject var setCol: SetColor
    @State private var navActive: Bool = false
    var body: some View {
        ZStack {
            Color(setCol.asyncVal ? .yellow : .orange)
            Button(action: {
                setCol.flipIt()
                navActive.toggle()
            }, label: {
                Text("Change and Move")
            })
            .navigationTitle("Nav 2")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    NavigationLink(destination: NavChild3().environmentObject(setCol),isActive: $navActive, label: { Text("GoTo 3 >") })
                }
            }
        }
    }
}

struct NavChild3: View {
    @EnvironmentObject var setCol: SetColor
    @State private var navActive: Bool = false
    var body: some View {
        ZStack {
            Color(setCol.asyncVal ? .yellow : .orange)
            Button(action: {
                setCol.flipIt()
                navActive.toggle()
            }, label: {
                Text("Change and Move")
            })
            .navigationTitle("Nav 3")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    NavigationLink(destination: NavChild3().environmentObject(setCol), isActive: .constant(false), label: { Text("Go Home") })
                }
            }
        }
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

你不需要在GCD行动中设定最后期限。即使用户没有按下导航键,它也会导致导航操作(我已经在项目中测试了代码)。 这是因为您在GCD队列中累积作业,当它们被执行时,您处于另一个视图中(由于0.5暂停)。顺便说一句,它们会导致导航,因为观察到翻转,因此任何侦听者都将执行导航

无论如何,您要做的是将dispatch命令更改为:

DispatchQueue.main.async { self.asyncVal.toggle() }

导航将更加顺畅,之后无需执行额外的导航命令。

最后期限仅适用于此示例。(实际事件是一个数据提取操作,但不想让人感到厌烦。)但它确实有延迟,不太长,但仍然有足够长的时间导致可观察到的“重复”。在这种情况下,我想我可以等待返回值,或者超时时发出警报,这不是什么大问题,但这是我关心的方法。考虑确保视图仅在顶部时更新。(最初已观察到,而不是当前绑定。)