简体   繁体   中英

SwiftUI Published updates not refreshing

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM