【问题标题】:Cocoa - Notification on NSUserDefaults value change?Cocoa - 关于 NSUserDefaults 值更改的通知?
【发布时间】:2010-11-11 14:24:47
【问题描述】:

假设我有一个键@"MyPreference",对应的值通过NSUserDefaults存储。

有没有办法在值被修改时得到通知?

或者可以通过绑定来完成吗? (但在这种情况下,我希望我的对象能够收到更改通知,而不是将值绑定到 UI 元素,以便我可以执行其他任务。)

我知道可以观察到NSUserDefaultsDidChangeNotification,但这似乎是一种全有或全无的方法,并且似乎没有一种机制可以获取已修改的特定键值对. (欢迎指正。)

【问题讨论】:

    标签: cocoa notifications preferences


    【解决方案1】:

    花了一整天的时间寻找答案,问问题10分钟后才找到答案……

    通过 Key-Value-Observing 找到解决方案:

    [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self
        forKeyPath:@"values.MyPreference"
        options:NSKeyValueObservingOptionNew
        context:NULL];
    

    或者,更简单地说(根据下面的评论):

    [[NSUserDefaults standardUserDefaults] addObserver:self
                                            forKeyPath:@"MyPreference"
                                               options:NSKeyValueObservingOptionNew
                                               context:NULL];
    

    【讨论】:

    • 您也可以在[NSUserDefaults standardUserDefaults] 上调用此方法,而不必预先添加“值”。到关键路径。其他参数保持不变。
    • 我无法按照 Quin 的建议使用 [NSUserDefaults standardUserDefaults] 让它工作。但是,不需要字符串 append,因为 ...forKeyPath:@"values.MyPreference"... 可以工作。此外,您需要实现 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; 才能实际捕获事件。
    • 嗨 TrevorL...尽管 stringByAppendingString: 不是必需的,但在创建通用方法时它会有所帮助 - (void) observePreference:(NSString *)pref { ...[@"values." stringByAppendingString:pref] ...
    • 但此方法仅适用于 Mac,不适用于 iOS
    • 第一个解决方案(使用NSUserDefaultsController)适用于 Mac,但第二个解决方案不起作用。
    【解决方案2】:

    斯威夫特:

    override func viewDidLoad() {
      super.viewDidLoad()
      NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "THE KEY", options: NSKeyValueObservingOptions.New, context: nil)
    }
    
    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
      // your logic
    }
    
    deinit {
      NSUserDefaults.standardUserDefaults().removeObserver(self, forKeyPath: "THE KEY")
    }
    

    【讨论】:

    • 不要忘记删除观察者,因为您正在解释完整的方法
    【解决方案3】:

    Apple 员工建议在此处使用 NSUserDefaultsDidChangeNotification 通知:https://devforums.apple.com/message/237718#237718

    【讨论】:

    • 这样做的缺点是,您无法知道更改了哪些设置。
    • 是的,你会认为他们至少会将更改后的键放在 NSUserDefaultsDidChangeNotification 的 userInfo 字典中,但不是:“此通知不包含 userInfo 字典。”更糟糕的是,何时发布 NSUserDefaultsDidChangeNotification 的唯一规范说它是在“更改持久域时”发布的。我可能需要 20 分钟的研究才能确切地确认这意味着什么,然后我不确定我是否会相信它。
    • 此方法还有一个缺点:如果外部程序更改了您应用的默认设置,例如使用 cmd "defaults write" 或 Prefs Editor 应用程序,您将不会收到通知。 OTOH,使用 KVO 技术会通知您。
    【解决方案4】:

    我同意@DenNukem。我使用的是NSKeyValueObservingOptionNew。但是这个函数开始给我BAD_ACCESS Code=1错误,无论我使用NSUserDefault来保存其他对象。如果您使用的是 Key-Value Observer (KVC),请注意 NSUserDefaults 上的 Zombie 问题。

    这里是解决方案的链接: NSUserDefaults and KVO issues

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-09
      • 2021-12-24
      • 2013-10-03
      • 2019-06-30
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      • 2010-10-19
      相关资源
      最近更新 更多