SwiftUI:如何使用UserDefaults保留@Published变量?

Sre*_*eni 3 swift5 swiftui xcode11

我希望持久保存@Published变量,以便每次重新启动应用程序时都相同。

我想在一个变量上同时使用@UserDefault和@Published属性包装。例如,我需要一个' @PublishedUserDefault var isLogedIn '。

我有以下propertyWrapper

import Foundation

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T

    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    var wrappedValue: T {
        get {
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的设置课程

import SwiftUI
import Combine

 class Settings: ObservableObject {

   @Published var isLogedIn : Bool = false

 func doLogin(params:[String:String]) {

        Webservice().login(params: params) { response in

            if let myresponse = response {                    
                    self.login = myresponse.login
                    }
               }
         }

}
Run Code Online (Sandbox Code Playgroud)

我的观点班

struct HomeView : View {
    @EnvironmentObject var settings: Settings
    var body: some View {
        VStack {
            if settings.isLogedIn {
            Text("Loged in")
            } else{
            Text("Not Loged in")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以制作覆盖持久性和发布性的单个属性包装器?

Pim*_*Pim 10

要保留数据,您可以使用@AppStorage属性包装器。但是,如果不使用,@PublishedObservableObject将不再发布有关更改数据的消息。要解决此问题,只需objectWillChange.send()从属性的willSet观察者处进行调用即可。

import SwiftUI

class Settings: ObservableObject {
    @AppStorage("Example") var example: Bool = false {
        willSet {
            // Call objectWillChange manually since @AppStorage is not published
            objectWillChange.send()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它为我发布,无需“objectWillChange.send()”。 (2认同)

Vic*_*rov 5

private var cancellables = [String:AnyCancellable]()

extension Published {
    init(wrappedValue defaultValue: Value, key: String) {
        let value = UserDefaults.standard.object(forKey: key) as? Value ?? defaultValue
        self.init(initialValue: value)
        cancellables[key] = projectedValue.sink { val in
            UserDefaults.standard.set(val, forKey: key)
        }
    }
}

class Settings: ObservableObject {
    @Published(key: "isLogedIn") var isLogedIn = false
    ...
}
Run Code Online (Sandbox Code Playgroud)

范例:https//youtu.be/TXdAg_YvBNE