Search code examples
xcodeswiftuiobservedobject

SwiftUI issues with Observed object


I am having problems getting ObservedObject to work. In this example I have a TabView with a Home and Settings tabs. On the Settings tab I have a button to toggle a bool to set if I purchased to remove ads or not.

The AdView text has an if condition, on an ObservedObject, but when I toggle the value the ad text doesn't go away / appear. If I close the app and re-launch, it updates correctly. How can I get this to update in realtime?

class Settings: ObservableObject {
@Published var purchasedRemoveAds: Bool {
    didSet {
        UserDefaults.standard.set(purchasedRemoveAds, forKey: "purchasedRemoveAds")
    }
}


init() {
    self.purchasedRemoveAds = UserDefaults.standard.bool(forKey: "purchasedRemoveAds")
  }
}

struct ContentView: View {

@State var tabSelect: Int
@ObservedObject var settings: Settings

var body: some View {
    TabView(selection: $tabSelect) {
        NavigationView {
            Home()
        }
        .tabItem {
            Image(systemName: "house")
            Text("Home")
        }
        .tag(0)
        
        NavigationView {
            SettingsView(settings: Settings())
        }
        .tabItem {
            Image(systemName: "gearshape")
            Text("Settings")
        }
        .tag(1)
    }
    
    //Show Ads at bottom of screen
    if !settings.purchasedRemoveAds {
        Text("AdView here").frame(height: 50).frame(maxWidth: .infinity).background(Color.green)
    }
    Spacer()
  }
}

struct SettingsView: View {
@ObservedObject var settings: Settings

var body: some View {
    List {
        
        Section(header: Text("In-App Purchases")) {
            Button {
                settings.purchasedRemoveAds.toggle()
            } label: {
                Text("Remove Ads")
            }
        }.listRowBackground(Color.gray.opacity(0.1))
    
    }
    .navigationTitle("Settings")
}

}

enter image description here


Solution

  • On this line, you're creating a new instance of Settings:

    SettingsView(settings: Settings())
    

    Because this instance of Settings is instantiated before the switch is changed, it has no idea that the UserDefaults have been adjusted.

    Instead, pass the existing instance:

    SettingsView(settings: settings)
    

    Also, look into @AppStorage where you can get some of this behavior for free from the system.