如何观察UserDefaults的变化?

Zor*_*gan 11 ios swift swiftui

我的看法是@ObservedObject

struct HomeView: View {

    @ObservedObject var station = Station()

    var body: some View {
        Text(self.station.status)
    }
 
Run Code Online (Sandbox Code Playgroud)

它根据Stringfrom更新文本Station.status

class Station: ObservableObject {
    @Published var status: String = UserDefaults.standard.string(forKey: "status") ?? "OFFLINE" {
        didSet {
            UserDefaults.standard.set(status, forKey: "status")
        }
    }      
Run Code Online (Sandbox Code Playgroud)

status但是,我需要更改my 中的值AppDelegate,因为这是我接收Firebase Cloud Messages的地方:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.

  // Print full message.
  let rawType = userInfo["type"]

  // CHANGE VALUE OF status HERE
}
Run Code Online (Sandbox Code Playgroud)

但如果我更改-status UserDefaults中的值AppDelegate,它在我看来不会更新。

在我看来,当发生变化时如何@ObservedObject通知我status

编辑:忘记提及上述示例中使用了 SwiftUI 2.0 beta 版本。

Asp*_*eri 20

这是可能的解决方案

import Combine

// define key for observing
extension UserDefaults {
    @objc dynamic var status: String {
        get { string(forKey: "status") ?? "OFFLINE" }
        set { setValue(newValue, forKey: "status") }
    }
}

class Station: ObservableObject {
    @Published var status: String = UserDefaults.standard.status {
        didSet {
            UserDefaults.standard.status = status
        }
    }

    private var cancelable: AnyCancellable?
    init() {
        cancelable = UserDefaults.standard.publisher(for: \.status)
            .sink(receiveValue: { [weak self] newValue in
                guard let self = self else { return }
                if newValue != self.status { // avoid cycling !!
                    self.status = newValue
                }
            })
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:SwiftUI 2.0UserDefaults允许您直接通过在视图中使用/观察AppStorage,所以如果您只需要在视图中使用该状态,您可以使用

struct SomeView: View {
    @AppStorage("status") var status: String = "OFFLINE"
    ...
Run Code Online (Sandbox Code Playgroud)