简体   繁体   English

SwiftUI @已发布和主线程

[英]SwiftUI @Published and main thread

Could someone explain why I get this warning: Publishing changes from background threads is not allowed;有人可以解释为什么我会收到此警告:不允许从后台线程发布更改; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.确保在 model 更新上发布来自主线程的值(通过接收(on :) 等运算符)。

I'm know that if I wrap the changes in DispatchQueue.main.async the problem goes away.我知道如果我将更改包装在DispatchQueue.main.async中,问题就会消失。 Why does it happen with some view modals and not others?为什么某些视图模式会发生这种情况,而其他视图模式则不会? I thought that since the variable has @Published it's automatically a publisher on main thread?我认为既然变量有@Published它会自动成为主线程上的发布者?

class VM: ObservableObject {
    
    private let contactsRepo = ContactsCollection()
    
    @Published var mutuals: [String]?
    
    func fetch() {
        contactsRepo.findMutuals(uid: uid, otherUid: other_uid, limit: 4) { [weak self] mutuals in
            guard let self = self else { return }
            if mutuals != nil {
                self.mutualsWithHost = mutuals // warning...
            } else {
                self.mutualsWithHost = []
            }
        }
    }
}

The @Published property wrapper creates a publisher of the declared type, nothing more. @Published属性包装器创建声明类型的发布者,仅此而已。 The documentation may be able to provide further clarity.文档可能能够提供进一步的清晰度。

As for it happening on some viewModels and not others, we wouldn't be able to tell here as we don't have the code.至于它发生在某些视图模型上而不是其他视图模型上,我们无法在这里说出来,因为我们没有代码。 However it's always best practice to use DispatchQueue.main.async block or .receive(on: DispatchQueue.main) modifier for combine as you've already figured out when updating your UI.然而,最好的做法是使用DispatchQueue.main.async块或.receive(on: DispatchQueue.main)修饰符进行组合,正如您在更新 UI 时已经发现的那样。

The chances are your other viewModel is already using the main thread or the properties on the viewModel aren't being used to update the UI, again without the code we'll never be sure.很有可能您的其他 viewModel 已经在使用主线程,或者 viewModel 上的属性没有用于更新 UI,同样没有我们永远无法确定的代码。

Evidently, contactsRepo.findMutuals can call its completion handler on a background thread.显然, contactsRepo.findMutuals可以在后台线程上调用其完成处理程序。 You need to ward that off by getting back onto the main thread.您需要通过回到主线程来避免这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM