当从另一个 ObservedObject 链接到 Published 属性时,视图不会对更改做出反应

Posted

技术标签:

【中文标题】当从另一个 ObservedObject 链接到 Published 属性时,视图不会对更改做出反应【英文标题】:View not reacting to changes of Published property when its chained from another ObservedObject 【发布时间】:2021-12-03 07:14:05 【问题描述】:

下面是拥有 ViewModel 的 SwiftUI 视图,逻辑是如果 viewModel.authenticationService.user 包含用户对象,那么它将显示 HomeView,否则将要求登录。所以最初 viewModel.authenticationService.user 是 nil 并且用户登录成功,用户对象不再是 nil。

查看

struct WelcomeView: View 
    
    @ObservedObject private var viewModel: WelcomeView.Model
    @State private var signInActive: Bool = false
    
    init(viewModel: WelcomeView.Model) 
        self.viewModel = viewModel
    
    
    var body: some View 
        if viewModel.authenticationService.user != nil 
            HomeView()
         else  
            LoginView()
        
     

视图模型

extension WelcomeView 
    
    final class Model: ObservableObject 
        
        @ObservedObject var authenticationService: AuthenticationService
        
        init(authenticationService: AuthenticationService) 
            self.authenticationService = authenticationService
        
    

身份验证服务

final class AuthenticationService: ObservableObject 
    
    @Published var user: User?
    private var authenticationStateHandle: AuthStateDidChangeListenerHandle?
    
    init() 
        addListeners()
    
    
    private func addListeners() 
        if let handle = authenticationStateHandle 
            Auth.auth().removeStateDidChangeListener(handle)
        
        
        authenticationStateHandle = Auth.auth()
            .addStateDidChangeListener  _, user in
                self.user = user
            
    
    
    static func signIn(email: String, password: String, completion: @escaping AuthDataResultCallback) 
        if Auth.auth().currentUser != nil 
            Self.signOut()
        
        Auth.auth().signIn(withEmail: email, password: password, completion: completion)
    

但是,当用户对象更新了某个值时,它不会更新视图。我不确定,因为我是反应式编程方式的新手。有一个 View -> ViewModel -> Service 链,并且发布的用户属性在 Service 类中,一旦用户登录,就会成功更新。

我是否需要在 ViewModel 中添加一个监听器来响应服务发布的属性?或者有什么直接的方法可以让这个场景工作并更新 UI?

【问题讨论】:

我猜 User 是一个类而不是一个结构,对吧?由于类是引用类型,@published 属性包装器不会注意到用户对象内的变化。 ObservedObject 包装器在类中不起作用。您可以使用 sink 和 ant cancelable 获取更新 【参考方案1】:

如果存在来自 View -> ViewModel -> Services 的链的情况:

@ObservedObject 不适用于课程。仅适用于 SwiftUI 视图(结构)。因此,如果您想通过服务观察视图模型的变化,您需要手动监听/订阅它。

self.element.$value.sink(
                receiveValue:  [weak self] _ in
                    self?.objectWillChange.send()
                
            )

您也可以使用.assign。了解更多详情here

【讨论】:

以上是关于当从另一个 ObservedObject 链接到 Published 属性时,视图不会对更改做出反应的主要内容,如果未能解决你的问题,请参考以下文章

仅当从另一个查询中选择时,SQL Select 语句才突然检索错误值

当从另一个控制器(弹出窗口)访问 UILabel(作为一个插座)时,它仍然为零

当从另一个应用程序启动时,应用程序失去了记住其堆栈的能力

当从另一个 ViewController 类调用方法时,Xcode 找到一个 nil 变量,其中不应该是任何变量

ObservedObject 不会注意到 ObservableObject Array 的变化

当从不同的类调用更改时,UIView IBOutlet 不会更改