BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

Using AppStorage to update other Views

Forums > SwiftUI

Hi,

I'm working on my first "real" app, and am trying to get user settings (stored using AppStorage) to update other views but it only works sometimes.

For example, I have a clock on one screen and showSeconds as an option. This is working fine (with a few seconds of delay to update the view).

SettingsView

    @AppStorage("showSeconds") var showSeconds: Bool = true

TimeView

import SwiftUI

struct TimeView: View {
    @State var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    @State var timeNow = ""
    let defaults = UserDefaults.standard

    let dateFormatter = DateFormatter()

     var body: some View {

         @State var showSeconds = defaults.bool(forKey: "showSeconds")

         if showSeconds == true {
             Text(timeNow)
                 .font(.extraLargeTitle)
                 .onReceive(timer) { _ in
                     self.timeNow = dateFormatter.string(from: Date())
                 }
                 .onAppear(perform: {dateFormatter.dateFormat = "h:mm:ss a"})
         } else {
             Text(timeNow)
                 .font(.extraLargeTitle)
                 .onReceive(timer) { _ in
                     self.timeNow = dateFormatter.string(from: Date())
                 }
                 .onAppear(perform: {dateFormatter.dateFormat = "h:mm a"})
         }
    }
}

But this test example does not.

SettingsView

    @AppStorage("showIcon") var showIcon: Bool = true

TestView

import SwiftUI

struct TestView: View {

    let defaults = UserDefaults.standard

    var body: some View {

        @State var showIcon = defaults.bool(forKey: "showIcon")

        if showIcon == true {
            Image(systemName: "sun")

        } else {
            Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
        }
    }
}

1      

Not sure why you need to use let defaults = UserDefaults.standard. If you are already using @AppStorage("showIcon"). On another note you might not see the sun because there is no "sun" in SFSymbols. Below code would do the same job...

struct ContentView: View {
    var body: some View {
        VStack(spacing: 10) {
            SettingsView()
            IconView()
        }
    }
}

struct SettingsView: View {
    @AppStorage("showIcon") var showIcon: Bool = false

    var body: some View {
        Button("Show Icon") {
            showIcon.toggle()
        }
    }
}

struct IconView: View {
    @AppStorage("showIcon") var showIcon: Bool = false

    var body: some View {
        if showIcon {
            Image(systemName: "sun.max")
        } else {
            Image(systemName: "moon")
        }
    }
}

1      

Thanks. I wasn't sure if I was redefining AppStorage by reusing that. That worked!

1      

This initializer @AppStorage("showIcon") var showIcon: Bool = false is not setting false as the value. That is the value to use if the key("showIcon") does not exist. For example when you launch your app first time, there is no such value and it will be false. To create the key, just set a value to the showIcon variable e.g. showIcon = false or showIcon.toggle()

PS. If this solves your challenge please mark your post as SOLVED.

1      

Save 50% in my WWDC sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Reply to this topic…

You need to create an account or log in to reply.

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.