我正在尝试将所有
@EnvironmentObject
转换为 @Environment
,但遇到了问题。 UserService
具有属性 user
,即 nil
。之后发生网络调用并且用户得到更新。这些更改会发布在视图中,但与以前不同,.onAppear()
不会再次触发。我需要这个,因为一旦我有了 user
我需要调用 ViewModel 中需要用户的方法。
这以前工作得很好,但我猜幕后肯定发生了一些变化。有没有新的方法来处理这个问题?
@Observable class UserService {
var user: User?
var handle: AuthStateDidChangeListenerHandle?
init() {
print("UserService int()")
}
func listen() {
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
self.getCurrentUser(uid: user?.uid)
})
}
func getCurrentUser(uid: String?) {
guard let uid = uid else { return }
Firestore.firestore().collection("users").document(uid).getDocument { documentSnapshot, error in
do {
self.user = try documentSnapshot?.data(as: User.self)
print("getCurrentUser", self.user?.displayName)
} catch {
print("error")
self.error = error.localizedDescription
}
}
}
}
struct DiscoverView: View {
@Environment(UserService.self) private var userService
var body: some View {
// OK gets updated when user is updated
Text(userService.user?.displayName ?? "nil")
.onAppear() {
print("onAppear")
if userService?.user {
//trigger something else
}
// will trigger once and wont trigger when user is updated
}
}
}
在您的情况下仅调用一次
onAppear
实际上是正确的行为以及应该如何。
仅当 SwiftUI 视图的(结构)标识发生更改时,
onAppear
才会被多次调用。视图状态的更改不会导致多次调用 onAppear
。
要观察您的情况下
User
的变化,正确的方法是使用onChange
:
Text(userService.user?.displayName ?? "nil")
.onChange(of: userService.user) { oldUser, newUser in
print("User changed: \(newUser?.displayName)")
}
.onAppear() {
print("onAppear")
}
如果
onAppear
在您的旧代码中被多次调用,这实际上可能表明您的视图层次结构和 SwiftUI 状态处理存在问题。
例如,使用条件视图修饰符可能会导致此问题。