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.
I'm know that if I wrap the changes in DispatchQueue.main.async
the problem goes away. 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?
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 = []
}
}
}
}
CodePudding user response:
Evidently, contactsRepo.findMutuals
can call its completion handler on a background thread. You need to ward that off by getting back onto the main thread.
CodePudding user response:
The @Published
property wrapper creates a publisher of the declared type, nothing more. 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.
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.