如果在设置中设置了开关,我会运行一段代码,如下所示:
UserDefaults.standard.bool(forKey: "signatureSwitchState")
let buttonState = UserDefaults.standard.object(forKey: "signatureSwitchState") as! Bool
if buttonState == true {
sign()
}
我的问题是,如果交换机从未被激活,程序将失败,因为编译器声明“致命错误:在展开可选值时意外发现nil”
我的问题是,当使用bool(例如上述声明中的开关)时,如何最好地防止零值。
我已经尝试过let语句和保护语句但是编译器抱怨这些不能和bool一起使用。
答案 0 :(得分:1)
您应该使用:
let buttonState = UserDefaults.standard.bool(forKey: "signatureSwitchState")
如果未明确设置该值,则返回false。
答案 1 :(得分:1)
如果您尝试从UserDefaults获取bool,可以使用
let buttonState = UserDefaults.standard.bool(forKey: "signatureSwitchState")
,
此函数返回一个Bool,因此您知道该值只能为true或false,如果它没有找到该键的值,则它将返回false。您正在使用的功能
UserDefaults.standard.object(forKey: "signatureSwitchState")
返回一个AnyObject?所以它可以是零。
答案 2 :(得分:1)
鲜为人知,但Apple强烈推荐:
注册默认值,直到用户第一次更改值时才会考虑这些值。
在applicationDidFinishLaunching
中 - 至少在第一次访问该值之前 - 注册键/值对。
let userDefaults = UserDefaults.standard
let defaultValues : [String : Any] = ["signatureSwitchState" : false]
userDefaults.register(defaults: defaultValues)
现在值永远不会nil
(我知道Bool
示例相当弱)
let buttonState = UserDefaults.standard.bool(forKey: "signatureSwitchState")
与#34;原语相比,对象更有利于这种方式。无论如何都不会nil
的类型。
答案 3 :(得分:0)
有几种方法可以做到这一点。既然这是一个bool,那么使用nil-coalescing ??
可能最简单:
let buttonState = UserDefaults.standard.object(forKey: "signatureSwitchState") as? Bool ?? false
或者,您可以使用guard
来执行此操作,这可能更强大:
guard let buttonState = UserDefaults.standard.object(forKey: "signatureSwitchState") as? Bool else { return }
if buttonState == true {
sign()
}
请注意,在这两种情况下,您都必须将强制展开(!
)更改为可选的展开(?
)。
答案 4 :(得分:0)
我有一个可能在将来有用的提示,虽然它不如picciano answer那么好,这绝对是正确的方法。
UserDefaults.standard.object(forKey: "signatureSwitchState")
会返回AnyObject
。
如果您尝试强制转换为Bool
(as! Bool
),如果返回的值不是Bool
,或者nil
,则会崩溃。相反,如果您有条件地投射(as? Bool
),您将收到Bool?
。这会将值转换为Bool
(如果存在),否则它会给你nil
(不会崩溃。
从那里,您可以使用nil合并运算符(Bool?
)将此Bool
转换为??
。如果有值,它会返回Bool
值,否则它将返回您给出的默认值。在这种情况下,false
。
另外,由于buttonState
已经是Bool
,因此没有理由将其与true
语句中的if
进行比较。直接使用它:
let buttonState = UserDefaults.standard.object(forKey: "signatureSwitchState") as? Bool ?? false
if buttonState {
sign()
}