设置包值返回nil

时间:2016-03-27 23:45:46

标签: ios swift settings nsuserdefaults

我在我的应用中添加了一个设置包,在Xcode中,它出现在我的项目树视图的根目录中。

Root.plist文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>StringsTable</key>
    <string>Root</string>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Type</key>
            <string>PSGroupSpecifier</string>
            <key>Title</key>
            <string>Service</string>
        </dict>
        <dict>
            <key>Type</key>
            <string>PSTextFieldSpecifier</string>
            <key>Title</key>
            <string>Hostname</string>
            <key>Key</key>
            <string>service_hostname</string>
   <!-- and so on -->

当我在iOS上打开“设置”应用时,条目显示在底部,我可以完美地显示和编辑我的设置。

但是我无法从代码中检索这些值。这是我的代码:

static func loadSettings() {

    let ud = NSUserDefaults.standardUserDefaults()
    ud.synchronize()

    Settings.hostName = ud.stringForKey("service_hostname")
    // etc
}

我也尝试了ud.objectForKeyud.valueForKey - 两者都返回nil

设置Settings.hostName Xcode调试器报告后,尽管我在“设置”应用中设置了显式值,但其值为nil

我看到了这个帖子(iPhone App : How to get default value from root.plist?),其中有人发布了一大块Objective-C代码,可以将Root.plist文件直接手动加载到NSMutableDictionary并调用NSUserDefaults.standardUserDefaults().registerDefaults但是这似乎是一个黑客(我无法让它在Swift中工作,因为编译器说stringByAppendingPathComponent不再存在)

为什么没有NSUserDefaults从“设置”应用中获取设置?

4 个答案:

答案 0 :(得分:12)

默认值可以从Settings.bundle获取并添加到UserDefaults。可以在AppDelegate.swift的{​​{1}}中调用以下函数。

didFinishLaunchingWithOptions

答案 1 :(得分:11)

显然原因是,如果response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); 中的我的设置已定义默认值且用户未明确设置值,那么“设置”应用中显示的值将是plist中的默认值文件,但plist API仍会返回NSUserDefaults

不幸的是,这意味着如果默认值是有意义的(例如默认的Web服务地址URI:“nil”),它必须在我的项目中存在两次:作为http://www.example.com中的默认值在我的程序代码中:

Root.plist:

plist

Program.swift:

  <dict>
      <key>Key</key>          <string>mySettingKey</string>
      <key>Title</key>        <string>Some address</string>
      <key>Type</key>         <string>PSTextFieldSpecifier</string>
      <key>DefaultValue</key> <string>http://www.example.com</string>
      <key>IsSecure</key>     <false />
      <key>KeyboardType</key> <string>Alphabet</string>
  </dict>

这令人惊讶。

答案 2 :(得分:7)

您应该注册默认设置,以便同步。 source from here

// Swift 3
var appDefaults = Dictionary<String, AnyObject>()
appDefaults["mySettingKey"] = "http://www.example.com" // Default Value

UserDefaults.standard.register(appDefaults)
UserDefaults.standard.synchronize()

let mySettingValue = UserDefaults.standard.string(forKey: "mySettingKey")

请记住,您还应该使用registerDefaults:当您的应用使用设置套装时。由于您已在设置包的plist中指定了默认值,因此您可能希望应用自动选择这些值。但事实并非如此。设置包中包含的信息仅由iOS Settings.app读取,绝不会被您的应用读取。为了让您的应用程序使用与Settings.app中显示的相同的默认值,您必须手动将用户默认值及其默认值复制到单独的plist文件中,并将其注册到默认数据库,如上所示。

答案 3 :(得分:0)

您需要从Settings.bundle中手动读取默认值,并将它们添加到UserDefaults注册域,这可以通过UserDefaults.register()完成。通过使用注册域,这些值将保存在内存中(易失性),因此不需要调用UserDefaults.synchronize()

雨燕4和5

以下几行Swift可以完成工作:

// Register the default values from Settings.bundle
if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"),
    let settingsRootDict = NSDictionary(contentsOf: settingsURL),
    let prefSpecifiers = settingsRootDict["PreferenceSpecifiers"] as? [NSDictionary],
    let keysAndValues = prefSpecifiers.map({ d in (d["Key"], d["DefaultValue"]) }) as? [(String, Any)] {
        UserDefaults.standard.register(defaults: Dictionary(uniqueKeysWithValues: keysAndValues))
}