I'm trying to manage user state via a series of nested classes.
The basic view of the app uses a globalState
environment object. This object allows other views to the user in and out.
@EnvironmentObject var globalState: GlobalState
// View Code
Text("Logged In").opacity(globalState.user.isLoggedIn ? 1 : 0)
Text("Please Sign In").opacity(globalState.user.isLoggedIn ? 0 : 1)
Then the GlobalState
class merely houses the User
class. The user
field is init'ed elsewhere (and no, I'm not referencing different user
objects).
class GlobalState: ObservableObject {
@Published public var user: User // Inited somewhere else
}
class User {
@Published var isLoggedIn: Bool = false
}
The User
class automatically pulls data about the user when it is init
ed. On app launch, user information is pulled from the Keychain (if present). If the user can be created from existing data, that user's isLoggedIn
is set to true
.
I know I do not have duplicate objects, as the memory addresses of the globalState.user
in GlobalState
's View Code is the same as when isLoggedIn
is updated for a user.
I feel a disturbance in the Force by using two levels of @Published
variables, but everything should work out?
The view code in GlobalState
does not update though. Any one know why? Some Combine jiu jitsu I'm missing?
ObservedObject
observes only one level of published properties, if you have hierarchy of ObservableObject
instances, you need to separated dependent views with own ObservedObject
for each such case.
@EnvironmentObject var globalState: GlobalState
// View Code - separated explicit subview
UserLoginStateView(user: globalState.user)
and
struct UserLoginStateView: View {
@ObservedObject var user: User
var body: some View {
Group {
Text("Logged In").opacity(user.isLoggedIn ? 1 : 0)
Text("Please Sign In").opacity(user.isLoggedIn ? 0 : 1)
}
}
}
@Published
publishes value changes, so if you would replace the User object it would update. Since User is a class (Reference type) it will not update the value of GlobalState.user when User.isLoggedIn changes.
Fix for this is this package called NestedPublished which sends the nested ObservableObject.willChange to its parent.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.