Search code examples
swiftuiapple-watch

@Appstorage is not updating based on my picker selection - SwiftUI - WatchApp


I have a picker that updates an variable bmr. the picker in not updating the value. I put a test Text on the second screen to see if I can call the new value, its always showing the default.

import SwiftUI

struct ProfileView: View {
    
    @AppStorage("ProfileView") var profileView:Bool = false
    @AppStorage("ContentView") var contentView:Bool = false
    @AppStorage("TimerView") var timerView:Bool = false
    @AppStorage("Name") var userName: String?
    @AppStorage("BMR") var bmr: Int?
    
    var body: some View {
        VStack {
            Picker(selection: $bmr, label: Text("Enter your BMR:")) {
                Text("50").tag(50)
                Text("60").tag(60)
                Text("70").tag(70)
                Text("80").tag(80)
            }
            NavigationLink(destination: ContentView()) {
                Text("Save")
            }
            
        }
    }
}

struct ContentView: View {
    
    @AppStorage("ProfileView") var profileView:Bool = false
    @AppStorage("ContentView") var contentView:Bool = false
    @AppStorage("TimerView") var timerView:Bool = false
    @AppStorage("Name") var userName: String?
    @AppStorage("BMR") var bmr: Int?
    
    var body: some View {
        VStack {
            Text("Your BMR: \(bmr ?? 50)")
            }
    }
    }

I am learning, so I don't know what to really try. I tried binding and unbinding, its not really working.

I tried to store variables and pass through views previously to test if it would update, and it worked fine. But passing info through views doesn't work with my app as I need this data to to be stored even if I exit.


Solution

  • The issue is bmr is an Int? while your tags are Int. Since they are not the same thing, the selection won't update it. The trick is to cast your tag as an Int? like this:

    struct ProfileView: View {
        
        @AppStorage("ProfileView") var profileView:Bool = false
        @AppStorage("ContentView") var contentView:Bool = false
        @AppStorage("TimerView") var timerView:Bool = false
        @AppStorage("Name") var userName: String?
        @AppStorage("BMR") var bmr: Int?
        
        var body: some View {
            VStack {
                Picker(selection: $bmr, label: Text("Enter your BMR:")) {
                    Text("50").tag(50 as Int?)
                    Text("60").tag(60 as Int?)
                    Text("70").tag(70 as Int?)
                    Text("80").tag(80 as Int?)
                }
                NavigationLink(destination: ContentView()) {
                    Text("Save")
                }
                
            }
        }
    }
    

    The tag and the selection types must EXACTLY match.