是否可以在带有 ScreenSaverDefaults 的笔尖中使用绑定?

Is it possible to use bindings in the nib with ScreenSaverDefaults?

我正在制作屏幕保护程序,所以我应该使用 ScreenSaverDefaults 而不是 NSUserDefaults。我想让我的配置面板为其 UI 使用绑定,但它们需要连接到 ScreenSaverDefaults,但我看不到这样做的方法; IB (xCode) 中唯一可用的默认控制器是标准用户默认控制器。是否有解决方法,或者只是无法在屏幕保护程序的上下文中使用笔尖中的绑定?

我已经在屏幕保护程序中成功使用了绑定。

(可能重要说明:我仍在使用 XC 3.2.6 在 10.6 上进行开发;到目前为止,此代码仅在 10.10 上进行了轻微测试(但似乎确实有效)。另外,我混合使用 C++ 和 Objective-C,因此您可能需要进行少量代码清理,如下所示。)

我的代码创建,UI 绑定到一个自定义用户默认控制器(控件绑定到文件所有者,设置为我的屏幕保护程序视图,控制器键为空,模型键路径是 self.defaultsController.values.key_val,其中 key_val 是默认 plist 中用于访问绑定到控件的值的任何键。

您还必须创建自己的屏幕保护程序默认值,并指示您的自定义用户默认值控制器使用它们,在屏幕保护程序初始化中(例如在 initWithFrame: 方法中您的屏幕保护程序视图),如下所示:

// Find our bundle:
NSBundle * screenSaverBundle = [NSBundle bundleForClass: [self class]];

// Load per-user screen saver defaults:
ScreenSaverDefaults * screenSaverDefaults = [ScreenSaverDefaults defaultsForModuleWithName: [screenSaverBundle bundleIdentifier]];

// Create default defaults (values to use when no other values have been established):
NSDictionary * defaultDefaultValues = [self defaultDefaults];

// Register default defaults as fallback values (in registration domain):
[screenSaverDefaults registerDefaults: defaultDefaultValues];

// Configure custom user defaults controller to use the correct defaults:
// NOTE: defaultsController of NSUserDefaultsController * type *MUST* be declared using @property in your header, and accessors must be provided (typically using @synthesize in the implementation section).
defaultsController = [[NSUserDefaultsController alloc] initWithDefaults: screenSaverDefaults initialValues: nil];   // <- change nil to factory defaults, if desired

// Make sure changes are only saved when committed by user:
[defaultsController setAppliesImmediately: false];

(以上代码是根据我自己代码中的各种方法稍微重新排列的;可能有一两个错字,但要点是正确的。)

defaultDefaults 的实现看起来像这样(请原谅我的非传统风格):

- (NSDictionary *) defaultDefaults
    {
    NSString * ResourcesPath = [[self screenSaverBundle] resourcePath];
    NSString * DefaultDefaultsPath = [ResourcesPath stringByAppendingPathComponent: @"DefaultDefaults.plist"];

    NSDictionary * DefaultDefaults = [NSDictionary dictionaryWithContentsOfFile: DefaultDefaultsPath];

    return DefaultDefaults;
    }

如果您想在屏幕保护程序中提供 "factory reset" 功能,您需要在创建自定义用户默认控制器时将 initialValues: 参数设置为 "original factory values" 字典。响应 "Reset to Factory Defaults" 按钮,只需将 revertToInitialValues: 发送到控制器。

最后请注意,根据上面代码中创建的某些对象的预期生命周期,您可能需要保留其中一些(并在以后适当释放它们)。我假设你了解这个 bhaller;我只是为一般观众指出这一点。

Swift版本:

首先,注册默认数据。

let defaults = ScreenSaverDefaults.init(forModuleWithName: "com.your.xxxx" ?? "")!
defaults.register(defaults: ["isShowSecond":true,
                             "userThemeIndex":0,
                             "userClockIndex":0
])

您可以设置值:

defaults.set(false, forKey: "isShowSecond")

您可以获得价值:

let defaults = ScreenSaverDefaults.init(forModuleWithName: "com.your.xxxx" ?? "")!
let userClockIndex = defaults.bool(forKey: "isShowSecond")