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?
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()
}
}