如何从ObserverableObject的ObserverableObject属性派生SwiftUI状态?

问题描述

这是我的示例SwiftUI项目。我有一个ObservableObject类(资源),该类可获取数据并使用@Published来发布其获取的值。

class Resource: ObservableObject {
    @Published var value: User?

    func savetoDb(email: String) {
        dispatchQueue.global().async {
            //save to remote db
            let user = User.init(email: email)
            dispatchQueue.main.async {
                self.value = user
            }
        }
    }
}

我还有第二个ObservableObject类(Authenticator),它表示一个身份验证状态,该状态也使用@Published来发布其状态。身份验证器的状态是从其资源是否具有值得出的。

class Authenticator: ObservableObject {

    @Published var needsAuthentication = true
    //Can this be derived from resource.value != nil instead of subscribing to it
    //UI doesn't appear to update when this is changed unless I use the subscription
    @Published var resource = Resource()

    var subscription: AnyCancellable?

    public init() {
        subscription = resource.$value.map({ (user: User?) -> Bool in
            user == nil
        })
        .receive(on: RunLoop.main)
        .assign(to: \Authenticator.needsAuthentication,on: self)
    }
    deinit {
        subscription?.cancel()
    }

    func doSignInWithAppleStuff() {
        let email = "fromSignInWithAppleResult@email.com"
        resource.savetoDb(email: email)
    }
}

我目前正在使用Combine docs中描述的步骤来订阅资源的值,并更新身份验证器和随后的UI。

struct ContentView: View {
    @StateObject var authenticator = Authenticator()
    var body: some View {
        //How do I skip using the authenticators state and use the resource directly?
        if authenticator.needsAuthentication {
            Button("Sign In") {
                authenticator.doSignInWithAppleStuff()
            }
        } else {
            Text("Success")
                .padding()
        }
    }
}
struct User {
    let email: String
}

是否有替代的SwiftUI / Combine工具可以帮助Autenticator.needsAuthentication属性表示资源具有值,而无需手动创建订阅

我尝试禁用订阅并使用$authenticator.resource.value.wrappedValue == nil,但是UI不会更新。我猜是因为身份验证器没有发布其资源属性的更改。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)