Swift - 如何为NSUserDefaults设置初始值

54

我有一个名为soundSwitch的开关,我正在使用userDefault保存按钮的状态,如下所示:

@IBAction func soundsChanged(sender: AnyObject) {
        if soundSwitch.on{
            defaults.setBool(true, forKey: "SoundActive")
            print("Sound ON")
        }else{
            defaults.setBool(false, forKey: "SoundActive")
            print("Sound OFF")
        }
    }

目前,当用户首次启动应用程序时,实际默认值最初为false。

如果用户启动了应用程序且尚未配置,则如何实现默认值为true。

我在Objective-C中看到了一些方法,但是在Swift中没有看到。从我所看到的,您可以在应用程序委托中以某种方式执行它,或者在PList文件中执行它。如何执行其中任何一个?


1
在你的 appDelegate 中,你可以检查 valueForKey 是否为 null。如果是 null,你可以将它设置为布尔值 true。 - Dominic
请查看:http://iosdevcenters.blogspot.com/2016/05/save-data-using-nsuserdefaults-in-swift.html - Kirit Modi
10个回答

80

Swift 3语法示例

注册一个布尔型默认值:

UserDefaults.standard.register(defaults: ["SoundActive" : true])

获取这个值的方法是:get

UserDefaults.standard.bool(forKey: "SoundActive")

顺便提一下:尽管上面的代码将返回true,但请注意,该值直到您设置它才实际写入磁盘:

UserDefaults.standard.set(true, forKey: "SoundActive")

1
“the value isn't actually written to disk until you set it”是什么意思?这是否意味着,如果在将来的版本中我从未设置默认值并从AppDelegate中删除了注册,那么键将无法检索到true,因为它从未手动设置过? - TomQDRS
1
@TomQDDRS,没错。引用 https://developer.apple.com/documentation/foundation/nsuserdefaults/1417065-registerdefaults?language=objc 中的话:“注册域的内容不会写入磁盘;您需要在每次应用程序启动时调用此方法。” - Fabian Streitel

31

将以下代码添加到AppDelegate的didFinishLaunchingWithOptions方法中。但是,要像其他人指出的那样,尽量避免滥用此方法并将所有内容都放在其中。

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

    /// Here you can give default values to your UserDefault keys
    UserDefaults.standard.register(defaults: [
        "SoundActive": true,
        "someOtherKey": "Some Message"
        ])
}

好的,register 方法。谢谢。 - Onur Tuna
这很繁琐。他们应该提供一种在检索时设置默认值的方式,而不是需要注册每一个东西。 - chitgoks

20

Swift 4

我喜欢实现一个类似于UserDefaults.string(forKey: )的函数,如果值未设置,则返回nil。结合 ?? 运算符,除非您稍后明确设置它们,否则不需要将任何默认值写入磁盘。

extension UserDefaults {

    public func optionalInt(forKey defaultName: String) -> Int? {
        let defaults = self
        if let value = defaults.value(forKey: defaultName) {
            return value as? Int
        }
        return nil
    }

    public func optionalBool(forKey defaultName: String) -> Bool? {
        let defaults = self
        if let value = defaults.value(forKey: defaultName) {
            return value as? Bool
        }
        return nil
    }
}

然后,您可以按以下方式检索默认值:

let defaults = UserDefaults.standard
let userName = defaults.string(forKey: "Username") ?? "Happy"
let userAge = defaults.optionalInt(forKey: "Age") ?? 21
let isSmart = defaults.optionalBool(forKey: "Smart") ?? true

太好了!这比注册所有东西更方便。 - chitgoks
不要使用value(forKey:),那是从键值编码继承下来的。请使用正确的UserDefaults API - object(forKey:) - HangarRash

9
使用 "registerDefaults" 可以设置 NSUserDefaults 的默认值。
let userDefaultsDefaults = [
            "SoundActive" : true
        ]

NSUserDefaults.standardUserDefaults().registerDefaults(userDefaultsDefaults)

注意:在didFinishLaunchingWithOptions中编写此内容,以设置默认值。

将以下代码编写在您想要检查的位置

 let onoroff = NSUserDefaults.standardUserDefaults().objectForKey("SoundActive") as! Bool!

 if (onoroff != nil && onoroff == false)
 {
    self.checkForAgreement()
 }

5

这段内容与Swift和应用委托无关。

通过在standardUserDefaults实例上调用registerDefaults:来设置初始默认值。

您可以多次进行此调用,我建议您不要在应用委托中执行此操作,而是在适当的时候注册适当的详细信息,以使代码的初始化部分作为默认值。例如,如果您有1个视图控制器/子系统使用了某些默认值,则在该代码的初始化过程中注册默认值。

仅当您有一些被多个不同代码部分使用的内容时,才应考虑在应用委托中执行此操作,但前提是您没有其他适当的控制器可供使用。


你为什么不在应用程序委托中完成它? - Daniel
1
因为应用程序委托存在特定目的,任意的用户默认注册不是其目的的一部分。@simpleBob - 作为应用程序的委托并处理应用程序级别事件是其唯一目的,没有其他。 - Wain
3
但是用户默认设置注册应该在任何其他操作之前完成,这就是为什么 didFinishLaunchingWithOptions 是一个相当明显的位置并且在大多数项目中都可以找到它。此外,我认为将所有默认设置放在一个地方比在整个项目中有多个 registerDefaults 更好。 - Daniel
应该在需要之前完成,并且应该在合适的地方完成。当然,您可以在应用程序委托中完成,但这不是应用程序委托的目的,只是因为这很容易,这就是大多数人这样做的原因。@simpleBob - Wain
1
我认为在需要默认注册时的问题在于有些人可能需要更早地使用它们,而忘记进行注册。 - Daniel

4
func lastStatus() -> Bool {
    let defaultValue = true
    if let value = default.valueForKey("SoundActive") {
        // then use it
        return value as? Bool ?? defaultValue
    } else {
        // oh, no value?
        return defaultValue
    }
}

我认为这是最好的使用方式。此外,register(defaults:)会有所帮助,但在文档中,苹果建议将其作为fallback,例如分离无值默认值的情况。根据您的需求而定。


4
你可以将所有的UserDefaults逻辑封装到一个属性变量中,该变量会自动注册应用程序默认值,并将任何更新保存回用户默认字典。如果应用程序的其他部分(除了开关控件)也读取或更改此状态,则特别方便。 Swift 5 — 第一部分执行闭包以初始化属性,第二部分是didSet块,每次更改属性时自动调用。
var soundIsActive: Bool = {
        // Register the app default:
        UserDefaults.standard.register(defaults: ["SoundActive" : true])

        // Initialize the property with the current user default:
        return UserDefaults.standard.bool(forKey: "SoundActive")
    }()
    {
        didSet {
            // Update user default when the variable is set:
            UserDefaults.standard.set(soundIsActive, forKey: "SoundActive")
        }
    }

0

如果您真的想以这种方式实现,将其放置在AppDelegate中:

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

    let defaults = NSUserDefaults.standardUserDefaults()
    if defaults.valueForKey("SoundActive") == nil {
        defaults.setBool(true, forKey: "SoundActive")
    }

如果代码仅在一个视图控制器中使用,请考虑将其放置在viewDidLoad方法中!

我认为这不是一个好的方式,因为每次启动应用程序时,它都会运行这些代码。但实际上,它只在第一次需要。 - Klein Mioke
好的,你进行编辑。但是我认为最好的方式是当你使用“SoundActive”的值时,如果为空则为True。 - Klein Mioke

0

如何设置默认值的通用版本:

enum UserDefaultsKeys: String {
    case username = "kUsername"
}

extension UserDefaults {
    func optionalValue<T>(forKey key: UserDefaultsKeys) -> T? {
        if let value = self.value(forKey: key.rawValue) {
            return value as? T
        }
        return nil
    }
}

let username = defaults.optionalValue(forKey: .username) ?? ""

-1
将以下代码放入AppDelegate的“didFinishLaunchingWithOptions”方法中。
if defaults.valueForKey("launchedAlready") == true {
       print("Not first launch.")
    }
    else {
       defaults.setValue(true, forKey: "launchedAlready")
        defaults.setBool(true, forKey: "SoundActive")
        print("Sound ON")
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接