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

时间:2017-09-27 17:22:17

标签: ios swift nsuserdefaults

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

public static void registerUser(String email, String password) {

    FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, 
    password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            if (task.isSuccessful()) {
                // Sign in success. Do things

            } else {
                // If sign in fails
                Log.d("AuthEngineDebugger", "Something went wrong");
            }
        }
    });

}

我在viewDidLoad中调用这些方法

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)
    }

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

5 个答案:

答案 0 :(得分:9)

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

Settings.bundle content

如果您希望能够从应用中的Settings.bundle访问UserDefaults中定义的默认值,则必须先注册它们。不幸的是,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)
}

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

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
}

答案 1 :(得分:5)

  

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

看起来您有一个切换开关,在设置包中显示为ON,当您读取包时,您将获得所有错误值。

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

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

enter image description here

我在Root.plist中将提醒的默认值设置为更新 因此,当应用程序启动时,它会显示如上所示。

但是当我尝试阅读这些默认值时 - 它同时为 false

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"))")
}
  

Update的默认值 - false Reminder的默认值 - false

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

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

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

  

提醒的默认值 - true

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

enter image description here

希望它有所帮助。

答案 2 :(得分:2)

添加LatinKeyboard的通知,如下所示:

UserDefaults.didChangeNotification

答案 3 :(得分:1)

这是一个基于@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)
}

所以对于这样的Root.plist

root.plis

... defaultsToRegister将是:

defaultsToRegister

这里还有the new compactMapValues() API in Swift 5可能对您没有帮助。

答案 4 :(得分:0)

我确实对你所问的问题有点麻烦,但听起来你已经创建了一个设置包plist,它指定一些默认值如果未定义则为“true”(如果用户没有'设置它们默认为true)。但是我想你做的时候:

let update_lot = defaults.bool(forKey: "update_lot")

...此代码无法知道“unset”应该评估为“true”而不是“false”。您可以改为使用defaults.object(forkey: "update_lot"),如果返回一个对象,则获取该对象的布尔值(或者只是在该点调用defaults.bool),但如果它返回nil,则认为它是真的。