使用我自己的(不是共享的)NSUserDefaults 对象的 KVO 和绑定问题
我在我的应用程序中对 NSUserDefaults 进行子类化。 这样做的副作用是我无法使用[NSUserDefaults sharedUserDefaults]
,我必须有一个类方法来提供我自己的静态默认对象。 这在代码中不是问题,但事实证明,现在我正在将首选项 UI 与绑定连接起来,这很棘手。
共享的 NSUserDefaultsController 使用共享的默认值,所以就这样了。 相反,我可以在窗口控制器中创建自己的默认控制器,为其提供静态默认对象,并将绑定连接到该对象。 但这并不完全有效。 当我尝试在默认对象上使用 KVO 时,我没有收到任何更改通知。 我使用常规 NSUserDefaults 对象(不是子类)再次尝试此操作,并且再次没有 KVO 通知。 替换共享默认对象后,KVO 完全按照我的预期工作。
有谁知道当我不使用共享默认值时如何让绑定和 KVO 工作?
I'm subclassing NSUserDefaults in my application. A side effect of this is I can't use [NSUserDefaults sharedUserDefaults]
, I have to have a class method to provide my own static defaults object. This isn't been a problem in code, but it's proving tricky now that I'm hooking up the preferences UI with bindings.
The shared NSUserDefaultsController uses the shared defaults, so that's out. Instead I can create my own defaults controller in my window controller, provide it with my static defaults object, and hook up my bindings to that. This doesn't fully work though. When I tried using KVO on my defaults object I didn't receive any change notifications. I tried this again with a regular NSUserDefaults object (not a subclass) and again, no KVO notifications. Substituting in the shared defaults object, KVO works exactly how I'd expect.
Does anyone have any ideas on how I can get bindings and KVO to work when I'm not using the shared defaults?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我总是用我自己的自定义类包装 NSUserDefaults 内容,以确保一切按预期工作。
工作流程基本上是这样的:
我发现应用程序设置的这种封装有助于消除所有令人头痛的问题。 您不必直接处理 Apple 神奇的 NSUserDefaults 系统,而是将时间花在与定义良好且易于测试的自定义类进行交互上。
I always wrap the NSUserDefaults stuff with my own custom class to make sure everything works as expected.
The workflow essentially goes like this:
I find that this encapsulation of the application settings helps to take away all of the headaches. Instead of dealing directly with Apple's magical NSUserDefaults system, you spend your time interacting with a well-defined and easily tested custom class.
我认为文档提供了答案。
init
方法初始化一个新实例,但不会在搜索路径中放入任何内容。 如果您要初始化自己的实例,则需要手动设置要使用的域。 我的猜测是您的应用程序无法运行,因为您尝试获取/设置的值不存在,因为没有域可以保存它们。特别是,请查看
addSuiteNamed: 方法和
NSUserDefaultsDomain
常量。 您需要手动设置这些,以使您的子类或除standardUserDefaults
之外的任何NSUserDefaults
实例正常工作。The documentation provides the answer, I think. The
init
method initializes a new instance, but doesn't put anything in the search path. If you're initializing your own instances, you'll need to set up the domains you intend to use by hand. My guess would be that your application isn't working because the values that you're trying to get/set don't exist because there are no domains to save them in.In particular, look at the
addSuiteNamed:
method and theNSUserDefaultsDomain
constants. You'll need to set these up by hand to make your subclass, or any instance ofNSUserDefaults
other thanstandardUserDefaults
, work properly.我最近一直在做类似的事情,到目前为止我的运气还不错。 我创建一个标准 NSObject 子类(参数为 MYUserDefaults)。 它具有我想要的属性(主机、用户名等)。有些属性属于 NSUserDefaults,有些属性属于钥匙串等。 它有一个标准的
+sharedUserDefaults
单例方法。 (*)在窗口所有者(NSWindowController 或 AppDelegate)中,我提供了一个
-sharedUserDefaults
。 然后,我使用简单的键路径(sharedUserDefaults.host)将其绑定到我想要的设置。 我通常会避免在绑定中使用键路径,因为它们经常会混淆事物,但在这里我认为它可以使一切保持清晰,同时处理需要防止 NIB 创建额外的非单例版本的特殊情况。(*) 没有花哨的“强制单例" 的东西(这也可能解决你的问题)。 我是唯一一个认为苹果应该在这份文档上大写“不要使用它,除非你知道为什么需要它,然后不要使用它”的人吗? 我发现让没有经验的开发人员看到这些代码是危险的。 我上一个项目中的一半对象都有
+allocWithZone:
重载。 对我来说,调用 +alloc 并获取指向现有对象的指针是一种不好的形式。 除非绝对必要,否则不要对我撒谎。I've been doing something similar just recently, and I'm having pretty good luck so far. I create a standard NSObject subclass (MYUserDefaults for argument). It has properties for the things I want (host, username, etc.) Some go to NSUserDefaults, some go to keychain or the like. It has a standard
+sharedUserDefaults
singleton method. (*)In the window owner (NSWindowController or AppDelegate), I provide a
-sharedUserDefaults
. I then bind through that to the settings I want with a simple keypath (sharedUserDefaults.host). I typically avoid keypaths in bindings because they often obfuscate things, but here I think it keeps everything clear while taking care of the special case that the NIB needs to be prevented from creating an extra non-singleton version.(*) No fancy "forced singleton" stuff (which might also fix your problem). Am I the only one who thinks Apple should have big flashing "don't use this unless you know why you need it, and then don't use it anyway" sign on this doc? I find that code dangerous to let inexperienced developers see. Half the objects in the last project I worked on had
+allocWithZone:
overloaded. To me it's just bad form to call+alloc
, and get pointers to existing objects. Don't lie to me unless it's absolutely necessary.由于我还没有找到解决方案,所以我决定采纳上次 CocoaHeads Syracuse 会议期间给我的一些建议,并改用类别而不是子类化 NSUserDefaults。 这不是一个完美的解决方案,但它会让我克服这个问题并重新开始工作。
Since I haven't found a solution yet, I decided to take some advice given to me during the last CocoaHeads Syracuse meeting and switch to using categories instead of subclassing NSUserDefaults. Not a perfect solution, but it'll let me get past this problem and back to work.