从旧式 KVO 切换到新的基于 Closure 的 API 打破了观察

问题描述 投票:0回答:1

我正在构建一个 macOS 应用程序。

我希望能够通过更新名为

showAtLaunch

的 UserDefaults 键来触发应用程序启动到不同模式

应用程序运行时我让它观察

showAtlaunch

let observer = UserDefaults.standard.observe(\.showAtLaunch, options: .new) { (foo, change) in
    // DO SOMETHING
}

问题是,当应用程序运行时,我从终端运行以下命令

defaults write ~/Library/Preferences/com.myMacOS.App.plist showAtLaunch 1

它会更新 plist 文件,但不会在应用程序中触发。

如果我使用以下代码:

UserDefaults.standard.addObserver(self, forKeyPath: "showAtLaunch", options: .new, context: nil)

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?,
                           context: UnsafeMutableRawPointer?) {
    print("""
          in observeValue keyPath: \(String(describing: keyPath))
          value: \(UserDefaults.standard.integer(forKey: "showAtLaunch"))
          """)
}

它按照我想要的方式工作,但 SwiftLint 需要

Block based KVO
因此我想使用新的 API 来观察事物。

对此的任何帮助或见解都会很棒!

swift macos key-value-observing
1个回答
0
投票

您需要保留(消失)通过调用

observe(:options:)
获得的返回类型,因为当它被破坏时,您的观察者将停止工作。所以如果你只这样做

let observer = UserDefaults.standard.observe(\.showAtLaunch, options: .new) { (foo, change) in
// DO SOMETHING
}

在函数内部,一旦函数完成,观察就会结束。

因此,向类型添加一个属性,该属性将在您的应用程序的整个生命周期中存在,或者只要您需要像主应用程序一样观察

一个 SwiftUI 示例

@main
struct MyApp: App {
    var defaultsObserver: NSKeyValueObservation
    //...
}

然后分配给

init
中的属性,或者将其设为可选,如果
init
不合适,稍后再执行。

© www.soinside.com 2019 - 2024. All rights reserved.