NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

SOLVED: How to make a saved published variable update immediately?

Forums > SwiftUI

I have two views in a tabview but the variable does not update on the second view until you restart the app. How do I make it updaate immediately?

Class:

class UserSettings: ObservableObject {
    @Published var score: Double {
        didSet{
            UserDefaults.standard.set(score, forKey: "score")
        }
    }
    init(){
        self.score = UserDefaults.standard.object(forKey: "score") as? Double ?? 0
    }
}

ContentView:

struct ContentView: View {

    @StateObject var userSettings = UserSettings()
    var body: some View {
        TabView{
            Settings()
                .tabItem{
            Label("Settings", systemImage: "person")
                }
            Home()
            .tabItem{
                Label("House", systemImage: "house")
            }

        }
    }
}

Home View:

struct Home: View {
    @ObservedObject var userSettings = UserSettings()
    var body: some View {
        Text("score: \(userSettings.score.formatted())")
    }
}

Settings View

struct Settings: View {
    @ObservedObject var userSettings = UserSettings()
    var body: some View {
        NavigationView{
            Form{
                Section(header: Text("Tap It")){
                    Button("Tap me"){
                        userSettings.score += 1
                    }

                }
            }
            .navigationTitle("Settings")
        }
    }
}

1      

You pasted UserSettings twice. You did not include ContentView.

Your score variable in UserSettings is capitalized. This convention is for defining structs and classes. Suggest you use lower case score, instead.

Would like to see ContentView (can you think of a better name for ContentView?) before making additional comments.

Why it matters


When I see code like

let currentScore = userSettings.Score.formatted()   // WHY are you using a class here?

I have to stop and think, WHY? Why is this programmer using a class in the middle of this? Is this some static definition?

1      

@Obelix I have made the changes, the reason I am using a class is because I thought I might be able to save the whole class at once (I can't figure out how).

1      

Here's what I think....

In your Settings view, you were creating a second UserSettings object. So when the application starts, it pulls the value from the user settings file. Just as you stated. But this second object never changes, so it never updates its view. What's confusing is you gave it the same name as the other UserSettings object.

So instead of creating a new, separate object (with the same name!) you should pass in the userSettings object created in your ContentView. Because it is an observed object, whenever it's changed elsewhere, the Settings view struct will redraw itself.

struct Settings: View {
    @ObservedObject var userSettings: UserSettings // Pass it in. Don't declare a new one.
    var body: some View {
        NavigationView{
        // ...... snip .............

Of course, this requires a small change to your ContentView code, right?

struct ContentView: View {
    @StateObject var userSettings = UserSettings()  // Yes! Declare one class object
    var body: some View {
        TabView{
            Settings(userSettings: userSettings)  // pass it in! 
                .tabItem{
                    Label("Settings", systemImage: "person")
                }
       // ....... snip ..........

PS: Nice updating your score variable. Now consider:

  1. Rename Settings to SettingsView. Why? It's a view! Not a collection of settings.
  2. Rename ContentView. Why? Just because.

2      

@Obelix Thakyou so much for your help I now understand the difference between the = and the : when it comes to observable objects. I however am not sure whether I will take on yor passion for changing the name of content View, but who knows.

1      

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.