Search code examples
buttonswiftuibooleanuserdefaults

UserDefaults using @State Bool Variable not saving State


I have a Button which switches State of a Color (Bool Type), foreground color and Borderframe color goes from blue to green. It works great. But now I want to save the State when I leave the "View" or when I close the app.

But I think it is not that easy with "Bool typ" like with just Strings.

import SwiftUI
struct CLPrepView: View {
    
    UserDefaults.standard.set(false, forKey: "colorsave")
    UserDefaults.standard.set(false, forKey: "bordersave")

    @State private var mycolor:Bool = false
    @State private var myborder:Bool = false

 var body: some View {
        
        ZStack {
            Color(.black)
                .ignoresSafeArea()
             
                Button(action: {
                    self.mycolor.toggle()
                    self.myborder.toggle()
                    UserDefaults.standard.set(mycolor, forKey: "colorsave")
                    UserDefaults.standard.set(myborder, forKey: "bordersave")
                }) {
                    
                    Text("Button")
                        
                }
                .frame(width: 600, height: 30, alignment: .leading)
                .padding(.all, 20)
                .background(.black)
                .foregroundColor(mycolor ? Color.green : Color.blue)
                .border(myborder ? Color.black : Color.blue)
}
}

Solution

  • in general it's best to use the @AppStorage property wrapper in SwiftUI, rather than try to manipulate UserDefaults directly. @AppStorage binds directly to the UserDefaults values in a way that's more SwiftUI friendly.

    struct AppStorageTest: View {
        
        //create and initialize @AppStorage property wrappers
        @AppStorage("myColor") var myColor:Bool = false
        @AppStorage("myBorder") var myBorder:Bool = false
    
        var body: some View {
            
            ZStack {
                Color(.black)
                    .ignoresSafeArea()
                
                Button(action: {
                    myColor.toggle() //changes happen immediately 
                    myBorder.toggle() //no need to write to UserDefaults
                }) {
                    Text("Button")
                }
                .frame(width: 600, height: 30, alignment: .leading)
                .padding(.all, 20)
                .background(.black)
                .foregroundColor(myColor ? Color.green : Color.blue)
                .border(myBorder ? Color.black : Color.blue)
            }
        }
    }
    

    confirm your defaults via the Terminal:

    $ defaults read org.myApp.BundleIdentifier
    {
        myBorder = 1;
        myColor = 1;
    }