使用我自己的(不是共享的)NSUserDefaults对象的KVO和Bindings问题

时间:2009-04-21 13:17:03

标签: objective-c cocoa cocoa-bindings nsuserdefaults key-value-observing

我在我的应用程序中继承了NSUserDefaults。这样做的副作用是我不能使用[NSUserDefaults sharedUserDefaults],我必须有一个类方法来提供我自己的静态默认对象。这在代码中并不是一个问题,但是现在我正在使用绑定来连接首选项UI,这是一个棘手的问题。

共享的NSUserDefaultsController使用共享的默认值,因此就是这样。相反,我可以在我的窗口控制器中创建自己的默认控制器,为其提供我的静态默认对象,并将我的绑定挂钩。但这并不完全有效。当我尝试在我的默认对象上使用KVO时,我没有收到任何更改通知。我再次尝试使用常规NSUserDefaults对象(不是子类),再次尝试没有KVO通知。替换共享的默认对象,KVO完全符合我的预期。

当我没有使用共享默认设置时,有没有人对如何使绑定和KVO工作有任何想法?

4 个答案:

答案 0 :(得分:2)

我总是用我自己的自定义类包装NSUserDefaults东西,以确保一切按预期工作。

工作流程基本上是这样的:

  1. 当应用程序启动时,将所有必需的NSUserDefaults条目读入自定义类。此自定义类具有每个设置的属性,并且所有NSDictionary和NSArray对象都是可变的,因此可以进行更改。
  2. 对设置进行更改的任何用户界面元素都绑定到自定义类的属性
  3. 根据需要,对设置的更改将保存到NSUserDefaults。

我发现应用程序设置的这种封装有助于消除所有令人头疼的问题。您不必直接与Apple神奇的NSUserDefaults系统打交道,而是花时间与定义明确且易于测试的自定义类进行交互。

答案 1 :(得分:1)

我认为文档提供了答案。 init方法初始化一个新实例,但不会在搜索路径中放置任何内容。如果您要初始化自己的实例,则需要设置要手动使用的域。我的猜测是你的应用程序无法运行,因为你试图获取/设置的值不存在,因为没有域可以保存它们。

特别是,请查看addSuiteNamed:方法和NSUserDefaultsDomain常量。您需要手动设置这些,以使您的子类或NSUserDefaults以外的任何standardUserDefaults实例正常工作。

答案 2 :(得分:1)

我最近一直在做类似的事情,到目前为止我运气不错。我创建了一个标准的NSObject子类(MYUserDefaults用于参数)。它具有我想要的东西的属性(主机,用户名等)。有些去了NSUserDefaults,有些去了钥匙串等。它有一个标准的+sharedUserDefaults单例方法。 (*)

在窗口所有者(NSWindowController或AppDelegate)中,我提供了-sharedUserDefaults。然后,我通过简单的密钥路径(sharedUserDefaults.host)将其绑定到我想要的设置。我通常会避免绑定中的键路径,因为它们经常混淆事物,但在这里我认为它可以保持一切清晰,同时处理需要防止NIB创建额外的非单例版本的特殊情况。

(*)没有花哨的“forced singleton”东西(这也可能解决你的问题)。我是唯一一个认为苹果应该有大闪光的人“除非你知道为什么需要它,否则不要使用它,然后不要使用它”在这个文件上签名?我发现代码很危险,让没有经验的开发人员看到。我工作的上一个项目中有一半的对象被+allocWithZone:重载了。对我来说,调用+alloc并获取指向现有对象的指针是一种糟糕的形式。除非绝对必要,否则不要欺骗我。

答案 3 :(得分:0)

由于我还没有找到解决方案,我决定在上次CocoaHeads Syracuse会议期间向我提出一些建议并切换到使用类别而不是子类化NSUserDefaults。不是一个完美的解决方案,但它会让我解决这个问题并重新开始工作。