Swift 4设置捆绑,获取默认值

use*_*331 6 nsuserdefaults ios swift

我创建了一个包含大约8个切换开关的设置包.我想要做的是从设置包中获取默认值.目前我现在有这两种方法:

func registerSettingsBundle(){
        let appDefaults = [String:AnyObject]()
        UserDefaults.standard.register(defaults: appDefaults)
        UserDefaults.standard.synchronize()
    }

    func updateDisplayFromDefaults(){
        let defaults = UserDefaults.standard
        let update_lot = defaults.bool(forKey: "update_lot")
        print(update_lot)
    }
Run Code Online (Sandbox Code Playgroud)

我在viewDidLoad中调用这些方法

override func viewDidLoad() {
        super.viewDidLoad()
        registerSettingsBundle()
        updateDisplayFromDefaults()
    }
Run Code Online (Sandbox Code Playgroud)

然而,这并没有得到我的默认值(这些都是真的,但它们都返回false).如果我关闭应用程序,打开设置,调整设置并重新打开应用程序,这会产生正确的值.有没有获得默认设置?我走了阅读plist的路线,但是如果我更改设置包中的设置,它将不会生效.

Kam*_*ski 15

为了演示,我们假设您在设置包中有两个开关.一个默认值设置为YES,另一个默认值设置为NO.

Settings.bundle内容

如果您希望能够访问在定义的默认值Settings.bundleUserDefaults您的应用程序,你必须先登记.不幸的是,iOS不会为你做,你必须自己照顾它.

以下方法扫描Root.plist与之关联的Settings.bundle并注册首选项标识符的默认值.

func registerDefaultsFromSettingsBundle()
{
    let settingsUrl = Bundle.main.url(forResource: "Settings", withExtension: "bundle")!.appendingPathComponent("Root.plist")
    let settingsPlist = NSDictionary(contentsOf:settingsUrl)!
    let preferences = settingsPlist["PreferenceSpecifiers"] as! [NSDictionary]

    var defaultsToRegister = Dictionary<String, Any>()

    for preference in preferences {
        guard let key = preference["Key"] as? String else {
            NSLog("Key not fount")
            continue
        }
        defaultsToRegister[key] = preference["DefaultValue"]
    }
    UserDefaults.standard.register(defaults: defaultsToRegister)
}
Run Code Online (Sandbox Code Playgroud)

我建议尽早运行它.您将确保应用的所有部分都有默认值.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
    registerDefaultsFromSettingsBundle()

    let one = UserDefaults.standard.bool(forKey: "switch_one")
    let two = UserDefaults.standard.bool(forKey: "switch_two")

    NSLog("One: \(one), Two: \(two)")

    return true
}
Run Code Online (Sandbox Code Playgroud)


man*_*mku 6

这不会得到我的默认值(都是真的,但它们都返回false)

看起来你有一个切换开关,在设置包中显示为ON,当你读取包时,你得到所有的错误值.

如果是这种情况,那么你在这里遗漏了一些东西.

在设置bundle(Root.plist)时,我们有"Default Value"字段,它与切换开关的实际默认值无关.这只是一个切换的视觉指示器.您可以在plist中将"Default value"设置为"YES",但是当您尝试读取该值时,您最终会变为false.

在此输入图像描述

在这里,我将Root.plist中的Reminder 默认值设置为YES,更新为 NO, 这样当应用启动时,它显示如上所示.

但是当我试图读取这些默认值时 - 它们都是假的.

func getDefaults() {        
    let stanDefaults = UserDefaults.standard
    print("Default value of Update - \(stanDefaults.bool(forKey: "update_lot_pref"))")
    print("\nDefault value of Reminder - \(stanDefaults.bool(forKey: "reminder_pref"))")
}
Run Code Online (Sandbox Code Playgroud)

默认值Update - false提醒的默认值 - false

现在,如果要同步这些值 - Root.plist中的默认值和默认值 - 那么您必须以编程方式设置它.

func setApplicationDefault() {
    let stanDefaults = UserDefaults.standard
    let appDefaults = ["reminder_pref": true]
    stanDefaults.register(defaults: appDefaults)
    stanDefaults.synchronize()
}
Run Code Online (Sandbox Code Playgroud)

在我的Root.plist中,我的默认值为YES,并且当viewDidload我将此首选项值设置为true时.我跑的时候给了我

提醒的默认值 - true

这就是我的Root.plist的样子.

在此输入图像描述

希望能帮助到你.


bac*_*h-f 5

这是基于 @Kamil 的答案(非常感谢),它不依赖NSDictionary并使用PropertyListSerialization.

雨燕5

func registerDefaultsFromSettingsBundle() {
    let settingsName                    = "Settings"
    let settingsExtension               = "bundle"
    let settingsRootPlist               = "Root.plist"
    let settingsPreferencesItems        = "PreferenceSpecifiers"
    let settingsPreferenceKey           = "Key"
    let settingsPreferenceDefaultValue  = "DefaultValue"

    guard let settingsBundleURL = Bundle.main.url(forResource: settingsName, withExtension: settingsExtension),
        let settingsData = try? Data(contentsOf: settingsBundleURL.appendingPathComponent(settingsRootPlist)),
        let settingsPlist = try? PropertyListSerialization.propertyList(
            from: settingsData,
            options: [],
            format: nil) as? [String: Any],
        let settingsPreferences = settingsPlist[settingsPreferencesItems] as? [[String: Any]] else {
            return
    }

    var defaultsToRegister = [String: Any]()

    settingsPreferences.forEach { preference in
        if let key = preference[settingsPreferenceKey] as? String {
            defaultsToRegister[key] = preference[settingsPreferenceDefaultValue]
        }
    }

    UserDefaults.standard.register(defaults: defaultsToRegister)
}
Run Code Online (Sandbox Code Playgroud)

所以对于Root.plist这样的:

根目录

...defaultsToRegister将是:

默认注册

Swift 5 中的compactMapValues()API 可能有帮助,也可能没有帮助。