首页 > 解决方案 > 即使不再显示,SwiftUI 视图也会不断更新

问题描述

我有一个简单的 View,它通过 @ObservedObject 属性观察一个对象。像这样的东西:

struct BrowserView: View {
    @ObservedObject var fs: FileStore

    var body: some View {
        List(fs.files) { file in
            NavigationLink(destination: BrowserView(fs: self.fs) {
                FileRow(item: file)
            }
        }
        .onAppear(perform: loadFiles)
    }

    private func loadFiles() {
        fs.loadFiles()
    }
}

所以发生的情况是,当点击一行时,我导航到下一个视图,它仍然是使用相同数据集的相同 BrowserView(在实际代码中,它还传递其他值,因为它就像文件浏览器一样,并且当前路径作为论点,但为了这个例子,它真的不相关)。

问题是,当下一个 BrowserView 出现时,数据集发生更改,并且这些更改触发了对不再可见的前一个 View 的更新,并且尝试更新其 UITableView 实际上会使应用程序崩溃。

有没有办法告诉 View 在 onDisappear 或类似的东西中禁用它的绑定?如果不是,那么当不同视图之间只有一个模型(存储)时,正确的模式是什么?

更新

以下是新视图被压入堆栈并检索到新数据时发生的情况的崩溃日志:

Thread 1 Queue : com.apple.main-thread (serial)
#0  0x00000001b9a4643c in AG::Graph::import_attribute(AG::Subgraph*, AG::Graph&, AG::attribute_t, AGTypeID, AG::ClosureFunctionVV<void>, AG::ClosureFunctionFV<void, AG::ClosureFunctionVV<void> >) ()
#1  0x00000001b9a4c76c in AGGraphImportAttribute ()
#2  0x00000001c52b8280 in ViewGraph.import<A>(_:as:from:) ()
#3  0x00000001c53a9a20 in static StyleType.makeViewList<A>(view:style:inputs:) ()
#4  0x00000001c53a9200 in static ResolvedList._makeViewList(view:inputs:) ()
#5  0x00000001c5203544 in closure #2 in static ModifiedContent<>._makeViewList(view:inputs:) ()
#6  0x00000001c51e723c in specialized static MultiViewModifier._makeViewList(modifier:inputs:body:) ()
#7  0x00000001c51e8274 in protocol witness for static ViewModifier._makeViewList(modifier:inputs:body:) in conformance ButtonActionModifier ()
#8  0x00000001c52020d8 in static ModifiedContent<>._makeViewList(view:inputs:) ()
#9  0x00000001c5203544 in closure #2 in static ModifiedContent<>._makeViewList(view:inputs:) ()
#10 0x00000001c51e81dc in static ViewModifier<>._makeViewList(modifier:inputs:body:) ()
#11 0x00000001c52020d8 in static ModifiedContent<>._makeViewList(view:inputs:) ()
#12 0x00000001c51795c0 in static View.makeViewList(view:inputs:) ()
#13 0x00000001c516b42c in static View._makeViewList(view:inputs:) ()
#14 0x00000001c542524c in AnyViewStorage.makeViewList(view:inputs:) ()
#15 0x00000001c54268a8 in closure #1 in AnyViewList.update(context:) ()
#16 0x00000001c5426648 in AnyViewList.update(context:) ()
#17 0x00000001c54289a0 in partial apply for protocol witness for static UntypedAttribute._update(_:graph:attribute:) in conformance AnyViewList ()
#18 0x00000001b9a3b88c in AG::Graph::UpdateStack::update() ()
#19 0x00000001b9a3bd48 in AG::Graph::update_attribute(unsigned int, bool) ()
#20 0x00000001b9a40cb0 in AG::Subgraph::update(unsigned int) ()
#21 0x00000001c52be0f4 in ViewGraph.runTransaction(in:) ()
#22 0x00000001c52bdea8 in closure #1 in ViewGraph.flushTransactions() ()
#23 0x00000001c52bdb20 in ViewGraph.flushTransactions() ()
#24 0x00000001c52bdc98 in closure #1 in closure #1 in ViewGraph.asyncTransaction<A>(_:mutation:style:) ()
#25 0x00000001c55759c0 in ViewRendererHost.updateViewGraph<A>(body:) ()
#26 0x00000001c52bdc60 in closure #1 in ViewGraph.asyncTransaction<A>(_:mutation:style:) ()
#27 0x00000001c52d9a30 in thunk for @escaping @callee_guaranteed () -> () ()
#28 0x00000001c514ff64 in static NSRunLoop.flushObservers() ()
#29 0x00000001c514fed4 in closure #1 in static NSRunLoop.addObserver(_:) ()
#30 0x00000001c5150004 in @objc closure #1 in static NSRunLoop.addObserver(_:) ()
#31 0x000000018d7acee8 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#32 0x000000018d7a7b78 in __CFRunLoopDoObservers ()
#33 0x000000018d7a8018 in __CFRunLoopRun ()
#34 0x000000018d7a78f4 in CFRunLoopRunSpecific ()
#35 0x0000000197bbe604 in GSEventRunModal ()
#36 0x000000019197b358 in UIApplicationMain ()

标签: iosswiftuicombine

解决方案


你所描述的不应该导致崩溃......试试这个代码:

class Model: ObservableObject {
    @Published var files: [String] = ["red", "black", "blue", "yellow", "orange"]
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            MainView(fs: Model())
        }
    }
}
struct MainView: View {
    @ObservedObject var fs: Model
    
    var body: some View {
        VStack {
            List(fs.files, id: \.self) {  file in
                NavigationLink(destination: MainView(fs: self.fs)) {
                    Text(file)
                }
            }.onAppear {
                self.fs.files.append("New Value")
            }
        }
    }
}

它正在观察模型并在 onAppear 中进行更新,并且一遍又一遍地推送相同的视图只会更新下一个屏幕中的列表以及第一个屏幕中的列表。


推荐阅读