Swift 中具有共享 NSUserDefaults 的 KVO

KVO with shared NSUserDefaults in Swift

我在通过传达 NSUserDefaults 更改时在我的主机应用程序及其扩展之间进行通信时遇到问题。

我使用 init(suiteName:) 初始化了 NSUserDefaults,使用 addObserver(...) 方法添加了 KVO 观察器并重写了方法 observeValueForKeyPath(...) 但未调用方法 observeValueForKeyPath(...)当我更改与观察 key 对应的值时。如果你能帮我解决这个问题,我将不胜感激。

PS:这里的套件名称是应用组名称,使用suiteName as group identifier创建的NSUserDefaults将在应用组的私有区域中。

iOS 10 开始,您可以在用户默认值上使用 KVO。

此问题已在 左右得到解答,因此我不会重新解决。

旧答案(iOS 9 岁及以上)

简短的回答是你不能在 NSUserDefaults 上使用 KVO 甚至 NSNotificationCenter 来传达应用程序扩展和包含应用程序之间的变化。

有一个 great post by Atomic Bird 着眼于协调沟通的方式。看看他对通信用户默认更改的分析尤其有趣:

A possible alternative for app/extension notifications is to use the Darwin notification center via CFNotificationCenterGetDarwinNotifyCenter, which actually is a little bit like NSDistributedNotificationCenter. There's some discussion of this by Wade Spires at Apple's dev forums site.

I say "possible" because I'm not 100% confident of this continuing to work. In the documentation for this method, Apple notes that

An application has only one Darwin notification center, so this function returns the same value each time it is called.

So although this is apparently legal, it also sounds a lot like it violates the philosophy inherent in app extension restrictions, viz, that they can't access anything from the hosting app. This is why [UIApplication sharedApplication] is off limits in extensions. I can't help wonder if allowing CFNotificationCenterGetDarwinNotifyCenter is an oversight that might get "fixed" at some point.

所以我想现在一个好的解决方案可能是使用 MMWormhole 因为他们实现了上述解决方案。

您的另一个选择是在您的应用程序每次激活时检查用户默认值并确认是否有任何密钥已更改,发布相关通知等。

祝你好运

刚刚测试过,对于 10.0 以上的 iOS 版本,UserDefatuls 的 KVO 在整个进程中工作得很好。