4

我正在向我的 iOS 应用程序添加一个 Settings.bundle 文件。只需一两个设置,它就非常少。Settings.bundle 中的 plist 文件为 Settings 应用程序指定默认值。我已经读过,为了让我的 iOS 应用程序知道这些默认值,我还必须将它们编码到我的应用程序中。这似乎是在重复我自己,并在我修改程序时为默认设置留下一个空缺,以便很容易地不同步。

我知道我可以使用 plist 文件的内容注册默认值,如下所示:

[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Defaults" ofType:@"plist"]]];

不过,这似乎也在重复我自己。是否可以使用 Settings.bundle 中的 plist 文件作为这些默认值的来源,以便我只在 1 个位置指定默认值?

我确实将负载调整为如下所示:

[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Settings.bundle/Root" ofType:@"plist"]]];

但是,那没有用。有谁知道这是否可能,以及如何加载该 plist 文件?

4

4 回答 4

3

Wanted to add this as a comment to Andy's answer, but Stack Overflow didn't let me (too long for a comment).
If you're using ObjC here's your version:

-(void)registerDefaults
{
    NSString* pathString = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Settings.bundle"];
    NSString* rootPath = [pathString stringByAppendingPathComponent:@"Root.plist"];
    NSDictionary* settingsDict = [NSDictionary dictionaryWithContentsOfFile:rootPath];
    NSArray* prefSpecifiers = settingsDict[@"PreferenceSpecifiers"] ;

    NSMutableDictionary* defaults = [NSMutableDictionary dictionary];

    for (NSDictionary* item in prefSpecifiers) {
        NSString* theKey = item[@"Key"];
        NSObject* defaultValue = item[@"DefaultValue"];

        if (defaultValue && theKey) {
            defaults[theKey] = defaultValue;
        }

    }

    if (defaults.count > 0) {
        [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
    }

}
于 2015-04-29T11:41:37.653 回答
1

对的,这是可能的。以下是您在 Swift 中的操作方式:

func loadDefaults() {

    let pathStr = NSBundle.mainBundle().bundlePath
    let settingsBundlePath = pathStr.stringByAppendingPathComponent("Settings.bundle")
    let finalPath = settingsBundlePath.stringByAppendingPathComponent("Root.plist")
    let settingsDict = NSDictionary(contentsOfFile: finalPath)
    let prefSpecifierArray = settingsDict?.objectForKey("PreferenceSpecifiers") as NSArray

    var defaults:[NSObject:AnyObject] = [:]

    for prefItem in prefSpecifierArray {

        if let key = prefItem.objectForKey("Key") as String! {

            let defaultValue:AnyObject? = prefItem.objectForKey("DefaultValue")
            defaults[key] = defaultValue
        }
    }

    _userDefaults.registerDefaults(defaults)
}

这将使用 Key 从每个 PreferenceSpecifier 加载 DefaultValue。例如:

<dict>
    <key>Type</key>
    <string>PSMultiValueSpecifier</string>
    <key>Title</key>
    <string>Frequency</string>
    <key>Key</key>
    <string>frequency</string>
    <key>DefaultValue</key>
    <integer>15</integer>
    <key>Titles</key>
    <array>
        <string>5 minutes</string>
        <string>15 minutes</string>
        <string>30 minutes</string>
        <string>60 minutes</string>
    </array>
    <key>Values</key>
    <array>
        <integer>5</integer>
        <integer>15</integer>
        <integer>30</integer>
        <integer>60</integer>
    </array>
</dict>

loadDefaults函数会将默认值 15 加载到“频率”的用户默认值中。

我建议您loadDefaults从处理程序中调用您的应用程序委托的didFinishLaunchingWithOptions函数,如下所示:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    loadDefaults()

    return true
}

然后稍后在您的应用程序中,例如在 a 中UITableViewController,您可以像这样加载用户默认值:

let kFrequency = "frequency"
frequency = _userDefaults.integerForKey(kFrequency)
于 2015-02-27T15:46:02.387 回答
0

根据上面Andy 的回答,适用于Swift 4,并避免使用 force-unwrap/force-cast:

private func loadDefaults() {
    let userDefaults = UserDefaults.standard

    let pathStr = Bundle.main.bundlePath
    let settingsBundlePath = (pathStr as NSString).appendingPathComponent("Settings.bundle")
    let finalPath = (settingsBundlePath as NSString).appendingPathComponent("Root.plist")
    let settingsDict = NSDictionary(contentsOfFile: finalPath)
    guard let prefSpecifierArray = settingsDict?.object(forKey: "PreferenceSpecifiers") as? [[String: Any]] else {
        return
    }

    var defaults = [String: Any]()

    for prefItem in prefSpecifierArray {
        guard let key = prefItem["Key"] as? String else {
            continue
        }
        defaults[key] = prefItem["DefaultValue"]
    }
    userDefaults.register(defaults: defaults)
}
于 2018-03-20T03:06:48.083 回答
-1

这不是必需的,您可以通过调用在 plist 中分配给它的键来简单地调用 plist 中的数据,例如,

_buttonSelection = [[NSUserDefaults standardUserDefaults] stringForKey:@"buttonAction01"]; //_buttonSelection is a NSString so that can be anything
于 2012-12-29T03:00:49.377 回答