UserDefaults не сохраняется и обновляется после первого раза в SwiftUI - PullRequest
2 голосов
/ 26 февраля 2020

Я создал простую систему для навигации по экрану в соответствии со значением UserDefaults , у меня есть ключ ”rootStatus” , который я поместил внутри перечисления. Я использовал @ PropertyWrapper для хранения значения по умолчанию для пользователя.

Поместить UserDefaults Key внутри перечисления.

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

Использовать оболочку свойств для сохранения данных в пользовательском значении по умолчанию.

//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)
        }
    }
}

Значение enum для хранения в UserDefaults .

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

Чтобы получить и установить значение UserDefaults , используя ObservableObject свойство 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 используется внутри 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())
            }
        }
    }

// при первом запуске приложения, поэтому я изначально установил пользовательское значение по умолчанию.

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

Измените значение в 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")
                }
            }
        }
    }
}

В ContentView я изменил пользовательское значение по умолчанию для выбора кнопок, но он не обновляется.

В чем может быть проблема?

1 Ответ

1 голос
/ 26 февраля 2020

Попробуйте следующее вместо ваших кнопок

final class ScreenSwitchSettings: ObservableObject {

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

и ..., когда вы помещаете в нее навигационную ссылку, она не работает, потому что последняя использует жест касания, поэтому протестируйте что-то вроде следующего

@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()
    }
}
...