2

I created a simple system to navigate on-screen according to the UserDefaults value, I have a key ”rootStatus” that key I placed inside the enum. I used @PropertyWrapper for storing the value of user default.

Place UserDefaults Key inside the enum.

  enum UserDefaultKey: String {
        case rootStatus           = "rootStatus"
    }

Use Property Wrapper to Save Data in the User Default.

//MARK: UserDefault:- storage template to occupies the memory in the local Database.
@propertyWrapper
struct UserDefault<T> {

    //Key: to storing the value in the userDefault in with name of specific key.
    let key: String
    //defaultValue:- to  storing the data in  any format in the UserDefault.
    let defaultValue: T

    //Update value when use a UserDefaultStorage inside the Project.
    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    // To Wrapping the Data inside the Project
    var wrappedValue: T {

        get{
             // Read value from UserDefaults
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }

        set{
            // Set value to UserDefaults.
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

Value of enum to store in UserDefaults.

enum ScreenSwitch: String {
    case lauched
    case logIn
    case dashboard
    case withoutlogin
    case none
}

To get and set the UserDefaults value using the ObservableObject property Wrapper.

final class ScreenSwitchSettings: ObservableObject {

    let objectWillChange = PassthroughSubject<Void, Never>()

    @UserDefault(UserDefaultKey.rootStatus.rawValue, defaultValue: ScreenSwitch.lauched.rawValue)
    var screenSwitch: String {
        willSet {
            objectWillChange.send()
        }
    }
}

TO used inside the SwiftView

 struct SwitchRootView: View {

            @ObservedObject var screenSwitchSettings = ScreenSwitchSettings()

        var body: some View {

 containedView()

        }

        func containedView() -> AnyView?{

            switch screenSwitchSettings.screenSwitch {

//// Introduction is a SwiftUIView for Navigation.
            case ScreenSwitch.lauched.rawValue : return AnyView(IntroductionView()) 

// LoginView is a SwiftUIView for Navigation.
            case ScreenSwitch.logIn.rawValue: return AnyView(LoginView())

// DashboardTabView is a SwiftUIView for Navigation. 
            case ScreenSwitch.withoutlogin.rawValue: return AnyView(DashboardTabView())

// DashboardTabView is a SwiftUIView for Navigation.
            case ScreenSwitch.dashboard.rawValue: return AnyView(DashboardTabView()) 

// EmptyView is a SwiftUIView for Navigation.
            case ScreenSwitch.none.rawValue: return AnyView(EmptyView()) 
            default : return AnyView(EmptyView())
            }
        }
    }

// when application launch first time so i set user default value in initially.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    @ObservedObject var screenSwitchSettings = ScreenSwitchSettings()

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        let contentView = SwitchRootView()
        screenSwitchSettings.screenSwitch = ScreenSwitch.lauched.rawValue
        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
}

Change the value in the SwiftUIView

struct ContentView: View {

    //MARK: Properties
    @ObservedObject var screenSwitchSettings = ScreenSwitchSettings()

    var body: some View {

        NavigationView{

            Button(action: {
                // here i change Userdefault Value.
                self.screenSwitchSettings.screenSwitch = ScreenSwitch.logIn.rawValue

            }) {

                NavigationLink(destination: SwitchRootView()) {

                    Text("Get Started")
                }
            }
        }
    }
}

In the ContentView, I changed the User default Value on the Button Selection but it's not updating.

What might be the problem?

halfer
  • 19,824
  • 17
  • 99
  • 186
Ravindra_Bhati
  • 1,071
  • 13
  • 28

1 Answers1

1

Try the following instead of your

final class ScreenSwitchSettings: ObservableObject {

  @UserDefault(UserDefaultKey.rootStatus.rawValue, defaultValue: ScreenSwitch.lauched.rawValue)
    var screenSwitch: String {
        willSet { // or even maybe on didSet
            self.objectWillChange.send()
        }
    }
}

and... button does not work when you place navigation link in it, because latter consumes tap gesture, so test with something like following

@State private var isActive = false

...
NavigationView{

    Button(action: {
        // here i change Userdefault Value.
        self.screenSwitchSettings.screenSwitch = ScreenSwitch.logIn.rawValue
        self.isActive.toggle()

    }) {
            Text("Get Started")
    }
    NavigationLink(destination: SwitchRootView(), isActive: $isActive) {
        EmptyView()
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690