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

发布于 2024-07-17 08:56:59 字数 445 浏览 9 评论 0原文

我在我的应用程序中对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜嗑 2024-07-24 08:56:59

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

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

  1. 当应用程序启动时,将所有必需的 NSUserDefaults 条目读取到自定义类中。 这个自定义类对每个设置都有一个属性,并且所有 NSDictionary 和 NSArray 对象都是可变的,以便可以进行更改。
  2. 对设置进行更改的任何用户界面元素都将绑定到自定义类的属性
  3. 对设置的更改将根据需要保存到 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:

  1. When the application launches, read all of the required NSUserDefaults entries into the custom class. This custom class has a property for each of the settings, and all of the NSDictionary and NSArray objects are mutable so that changes can be made.
  2. Any user interface elements that make changes to the settings are bound to the properties of the custom class
  3. Changes to the settings are saved to NSUserDefaults as required.

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.

等往事风中吹 2024-07-24 08:56:59

我认为文档提供了答案。 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 the NSUserDefaultsDomain constants. You'll need to set these up by hand to make your subclass, or any instance of NSUserDefaults other than standardUserDefaults, work properly.

幸福还没到 2024-07-24 08:56:59

我最近一直在做类似的事情,到目前为止我的运气还不错。 我创建一个标准 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.

_畞蕅 2024-07-24 08:56:59

由于我还没有找到解决方案,所以我决定采纳上次 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文