UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

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

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.