当从另一个 ObservedObject 链接时,View 不会对 Published 属性 的更改做出反应
View not reacting to changes of Published property when its chained from another ObservedObject
下面是 SwiftUI 视图,它拥有一个 ViewModel,逻辑是如果 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()
}
}
ViewModel
extension WelcomeView {
final class Model: ObservableObject {
@ObservedObject var authenticationService: AuthenticationService
init(authenticationService: AuthenticationService) {
self.authenticationService = 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 class 中,一旦用户登录就会成功更新。
我是否需要在 ViewModel 中添加一个侦听器来响应已发布的服务 属性?或者有什么直接的方法可以使这种情况起作用并获得 UI 更新?
如果存在从 View -> ViewModel -> Services 的链的情况:
@ObservedObject
不适用于 类。仅适用于 SwiftUI 视图(结构)。因此,如果您想从服务中观察视图模型的变化,您需要手动 listen/subscribe 它。
self.element.$value.sink(
receiveValue: { [weak self] _ in
self?.objectWillChange.send()
}
)
您也可以使用.assign
。查找更多详细信息 here
下面是 SwiftUI 视图,它拥有一个 ViewModel,逻辑是如果 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()
}
}
ViewModel
extension WelcomeView {
final class Model: ObservableObject {
@ObservedObject var authenticationService: AuthenticationService
init(authenticationService: AuthenticationService) {
self.authenticationService = 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 class 中,一旦用户登录就会成功更新。
我是否需要在 ViewModel 中添加一个侦听器来响应已发布的服务 属性?或者有什么直接的方法可以使这种情况起作用并获得 UI 更新?
如果存在从 View -> ViewModel -> Services 的链的情况:
@ObservedObject
不适用于 类。仅适用于 SwiftUI 视图(结构)。因此,如果您想从服务中观察视图模型的变化,您需要手动 listen/subscribe 它。
self.element.$value.sink(
receiveValue: { [weak self] _ in
self?.objectWillChange.send()
}
)
您也可以使用.assign
。查找更多详细信息 here