在 Swift/Xcode 6 中返回设置包开关的值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30217540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 07:08:40  来源:igfitidea点击:

Returning the value of a settings bundle switch in Swift / Xcode 6

iosswiftxcode

提问by MJQZ1347

I have difficulties returning the value of a stored boolean key.

我很难返回存储的布尔键的值。

My root.plist looks like this:

我的 root.plist 看起来像这样:

enter image description here

在此处输入图片说明

I've got this in AppDelegate:

我在 AppDelegate 中有这个:

    let a = NSUserDefaults.standardUserDefaults().boolForKey("sound")

    if a { // This is where it breaks
        println("sound is on")
    }

Any ideas what I'm doing wrong?

任何想法我做错了什么?

回答by Mark McCorkle

First you should register your defaults so everything is sync'd up and defaults are assigned. Then you'll know a value exists. These values are not automatically synchronized on startup.

首先,您应该注册默认值,以便同步所有内容并分配默认值。然后你就会知道一个值存在。这些值在启动时不会自动同步。

var appDefaults = Dictionary<String, AnyObject>()
appDefaults["sound"] = false
NSUserDefaults.standardUserDefaults().registerDefaults(appDefaults)
NSUserDefaults.standardUserDefaults().synchronize()

let a = NSUserDefaults.standardUserDefaults().boolForKey("sound")

if a { // This is where it breaks
    println("sound is on")
}

Below is an excerpt from a relevant article.

以下是相关文章的摘录。

When Your App Uses a Settings Bundle

当您的应用程序使用设置包时

Keep in mind that you should also use registerDefaults: when your app uses a Settings Bundle. Since you already specified default values inside the settings bundle's plist, you may expect that your app picks these up automatically. However, that is not the case. The information contained in the settings bundle is only read by the iOS Settings.app and never by your app. In order to have your app use the same defaults as shown inside the Settings.app, you have to manually copy the user defaults keys and their default values into a separate plist file and register it with the defaults database as shown above.

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

And HEREis the relevant discussion directly from Apple.

这里是从苹果直接相关的讨论。

Registering Defaults

注册默认值

Discussion

讨论

If there is no registration domain, one is created using the specified dictionary, and NSRegistrationDomain is added to the end of the search list. The contents of the registration domain are not written to disk; you need to call this method each time your application starts. You can place a plist file in the application's Resources directory and call registerDefaults: with the contents that you read in from that file.

如果没有注册域,则使用指定的字典创建一个,并将 NSRegistrationDomain 添加到搜索列表的末尾。注册域的内容不写入磁盘;每次应用程序启动时都需要调用此方法。您可以将 plist 文件放在应用程序的 Resources 目录中,并使用从该文件中读入的内容调用 registerDefaults:。

回答by Hugo Alonso

Use this:

用这个:

    var myDict: NSDictionary?
// Read from the Configuration plist the data to make the state of the object valid.
    if let path = NSBundle.mainBundle().pathForResource("root", ofType: "plist") {
        myDict = NSDictionary(contentsOfFile: path)
    }

    // Set the values to init the object
    if let dict = myDict {
        if let a = dict["sound"] as? Bool {
         if a { 
            println("sound is on")
          }
        }
    }

回答by atomoil

I came this post as I had the same issue today, and wasn't very satisfied with this note:

我今天遇到了同样的问题,所以我来到了这篇文章,对这个注释不是很满意:

In order to have your app use the same defaults as shown inside the Settings.app, you have to manually copy the user defaults keys and their default values into a separate plist file and register it with the defaults database as shown above.

为了让您的应用使用与 Settings.app 中显示的相同的默认值,您必须手动将用户默认键及其默认值复制到单独的 plist 文件中,并将其注册到默认数据库中,如上所示。

I thought there must be a more DRY solution, so I made the following extension. It iterates through the Settings.bundle's plists (including Child plists) and registers any DefaultValuesit finds. Also available in this gist.

我认为必须有一个更 DRY 的解决方案,所以我做了以下扩展。它遍历 Settings.bundle 的 plists(包括 Child plists)并注册DefaultValues它找到的任何内容。也可以在这个 gist 中找到

extension UserDefaults {

    static func syncSettingsBundle() {
        if let bundlePath = Bundle.main.path(forResource: "Settings", ofType: "bundle"),
            let plistPath = URL(string: bundlePath)?.appendingPathComponent("Root.plist").absoluteString {

            let defaultDefaults = UserDefaults.defaultsForPlist(path: plistPath, defaults: [:])
            UserDefaults.standard.register(defaults: defaultDefaults)
        }
    }

    static private func defaultsForPlist(path: String, defaults: [String: Any]) -> [String: Any] {
        var mutableDefaults = defaults
        if let plistXML = FileManager.default.contents(atPath: path) {
            do {
                let plistData = try PropertyListSerialization.propertyList(from: plistXML,
                                                                           options: .mutableContainersAndLeaves,
                                                                           format: nil) as! [String:AnyObject]
                if let prefs = plistData["PreferenceSpecifiers"] as? Array<[String: Any]> {
                    prefs.forEach { (pref: [String : Any]) in
                        if let key = pref["Key"] as? String,
                            let value = pref["DefaultValue"] {
                            mutableDefaults[key] = value
                        } else if let type = pref["Type"] as? String,
                            type == "PSChildPaneSpecifier",
                            let file = pref["File"] as? String,
                            let childPath = URL(string: path)?
                                .deletingLastPathComponent()
                                .appendingPathComponent(file)
                                .absoluteString {
                            mutableDefaults = UserDefaults.defaultsForPlist(path: childPath, defaults: mutableDefaults)
                        }
                    }
                } else {
                    print("Error no PreferenceSpecifiers in \(path)")
                }
            } catch {
                print("Error reading plist: \(error) in \(path)")
            }
        } else {
            print("No plist found found at \(path)")
        }
        return mutableDefaults
    }
}