当我想检查 Optional Bool 是否为真时,这样做不起作用:
var boolean : Bool? = false
if boolean{
}
它导致此错误:
可选类型'@IvalueBool?'不能用作布尔值;改为测试 '!= nil'
我不想检查零;我想检查返回的值是否为真。
如果我使用 Optional Bool,我是否总是必须做 if boolean == true
?
由于 Optionals 不再符合 BooleanType
,编译器不应该知道我要检查 Bool 的值吗?
使用可选的布尔值,需要明确检查:
if boolean == true {
...
}
否则,您可以打开可选的:
if boolean! {
...
}
但是,如果 boolean 为 nil
,则会生成运行时异常 - 以防止:
if boolean != nil && boolean! {
...
}
在 beta 5 之前它是可能的,但它已按照发行说明中的报告进行了更改:
选项不再在有值时隐式计算为真,在没有值时为假,以避免在使用可选 Bool 值时产生混淆。相反,使用 == 或 != 运算符对 nil 进行显式检查,以查明可选项是否包含值。
附录:正如@MartinR 所建议的,第三个选项的更紧凑的变体是使用合并运算符:
if boolean ?? false {
// this code runs only if boolean == true
}
这意味着:如果 boolean 不是 nil,则表达式计算为布尔值(即使用未包装的布尔值),否则表达式计算为 false
可选绑定
斯威夫特 3 & 4
var booleanValue : Bool? = false
if let booleanValue = booleanValue, booleanValue {
// Executes when booleanValue is not nil and true
// A new constant "booleanValue: Bool" is defined and set
print("bound booleanValue: '\(booleanValue)'")
}
斯威夫特 2.2
var booleanValue : Bool? = false
if let booleanValue = booleanValue where booleanValue {
// Executes when booleanValue is not nil and true
// A new constant "booleanValue: Bool" is defined and set
print("bound booleanValue: '\(booleanValue)'")
}
如果 booleanValue
是 nil
并且 if
块不执行,则代码 let booleanValue = booleanValue
返回 false
。如果 booleanValue
不是 nil
,则此代码定义一个名为 booleanValue
的新变量,类型为 Bool
(而不是可选的 Bool?
)。
斯威夫特 3 & 4 代码 booleanValue
(和 Swift 2.2 代码 where booleanValue
)评估新的 booleanValue: Bool
变量。如果为真,则 if
块在范围内使用新定义的 booleanValue: Bool
变量执行(允许选项在 if
块内再次引用绑定值)。
注意:将绑定的常量/变量命名为与可选常量/变量(例如 let booleanValue = booleanValue
)相同的名称是 Swift 约定。这种技术称为可变阴影。您可以打破常规,使用 let unwrappedBooleanValue = booleanValue, unwrappedBooleanValue
之类的东西。我指出这一点是为了帮助理解正在发生的事情。我建议使用可变阴影。
其他方法
无合并
对于这种特定情况,零合并很明显
var booleanValue : Bool? = false
if booleanValue ?? false {
// executes when booleanValue is true
print("optional booleanValue: '\(booleanValue)'")
}
检查 false
不是很清楚
var booleanValue : Bool? = false
if !(booleanValue ?? false) {
// executes when booleanValue is false
print("optional booleanValue: '\(booleanValue)'")
}
注意:if !booleanValue ?? false
不编译。
强制展开可选(避免)
强制解包增加了某人将来进行更改的机会,该更改编译但在运行时崩溃。因此,我会避免这样的事情:
var booleanValue : Bool? = false
if booleanValue != nil && booleanValue! {
// executes when booleanValue is true
print("optional booleanValue: '\(booleanValue)'")
}
一般方法
尽管此堆栈溢出问题专门询问如何在 if
语句中检查 Bool?
是否为 true
,但它有助于确定一种通用方法,无论是检查真假还是将展开的值与其他表达式组合。
随着表达式变得越来越复杂,我发现可选绑定方法比其他方法更灵活、更容易理解。请注意,可选绑定适用于任何可选类型(Int?
、String?
等)。
if let
?
while array.last < threshold { array.removeLast() }
if, let, where
完成堆栈处理,使用以下命令:Swift 2 中的 while let last = array.last where last < threshold { array.removeLast() }
或 Swift 3 中的 while let last = array.last, last < threshold { array.removeLast() }
。
while let
。
var enabled: Bool? = true
if enabled == true {
print("when is defined and true at the same moment")
}
if enabled == false {
print("when is defined and false at the same moment")
}
if let enabled = enabled, enabled == true {
print("when is defined and true at the same moment")
}
if let enabled = enabled, enabled == false {
print("when is defined and false at the same moment")
}
if let enabled = enabled, enabled {
print("when is defined and true at the same moment")
}
if let enabled = enabled, !enabled {
print("when is defined and false at the same moment")
}
if enabled ?? false {
print("when is defined and true at the same moment")
}
if enabled == .some(true) {
print("when is defined and true at the same moment")
}
if enabled == (true) {
print("when is defined and true at the same moment")
}
if case .some(true) = enabled {
print("when is defined and true at the same moment")
}
if enabled == .some(false) {
print("when is defined and false at the same moment")
}
if enabled == (false) {
print("when is defined and false at the same moment")
}
if enabled == .none {
print("when is not defined")
}
if enabled == nil {
print("when is not defined")
}
我找到了另一个解决方案,重载布尔运算符。例如:
public func < <T: Comparable> (left: T?, right: T) -> Bool {
if let left = left {
return left < right
}
return false
}
这可能并不完全符合语言更改的“精神”,但它允许安全地展开选项,并且它可用于任何地方的条件,包括 while 循环。
我发现最容易阅读的答案是定义一个函数。不是很复杂,但确实有效。
func isTrue(_ bool: Bool?) -> Bool {
guard let b = bool else {
return false
}
return b
}
用法:
let b: Bool? = true
if isTrue(b) {
// b exists and is true
} else {
// b does either not exist or is false
}
正如Antonio所说
选项不再在有值时隐式计算为真,在没有值时为假,以避免在使用可选 Bool 值时产生混淆。相反,使用 == 或 != 运算符对 nil 进行显式检查,以查明可选项是否包含值。
我花了几个小时试图理解我偶然发现的一行代码,但这个线程让我走上了正确的轨道。
此引用来自 august 2014,从那时起 Apple 在 proposal SE-0102 之后引入了 Never
,后者使其符合 Equatable, Hashable, Error and Comparable
现在可以使用 Never?
检查布尔值是否为 nil
:
var boolean: Bool? = false
boolean is Never? // false
boolean = true
boolean is Never? // false
boolean = nil
boolean is Never? // true
您实际上可以使用任何其他不适合居住的类型:
public enum NeverEver { }
var boolean: Bool? = false
boolean is NeverEver? // false
boolean = true
boolean is NeverEver? // false
boolean = nil
boolean is NeverEver? // true
话虽如此,现在也可以使用 property wrapper :
@propertyWrapper struct OptionalBool {
public var wrappedValue: Bool?
public var projectedValue: Bool { wrappedValue ?? false }
public init(wrappedValue: Bool?) {
self.wrappedValue = wrappedValue
}
}
struct Struct {
@OptionalBool var predicate: Bool?
var description: String {
if $predicate {
return "predicate is true"
}
return "predicate is false"
}
}
var object = Struct()
object.description // "predicate is false"
object.predicate = false
object.description // "predicate is false"
object.predicate = true
object.description // "predicate is true"
甚至:
@propertyWrapper struct OptionalBool {
var wrappedValue: Bool?
var projectedValue: OptionalBool { self }
var isNil: Bool { wrappedValue is Never? }
var value: Bool { wrappedValue ?? false }
init(wrappedValue: Bool?) {
self.wrappedValue = wrappedValue
}
}
struct Struct {
@OptionalBool var predicate: Bool?
var description: String {
if $predicate.value {
return "predicate is true"
}
if !$predicate.isNil {
return "predicate is false"
}
return "predicate is nil"
}
}
var object = Struct()
object.description // "predicate is nil"
object.predicate = false
object.description // "predicate is false"
object.predicate = true
object.description // "predicate is true"
if let
也可以。if boolean ?? false { ... }
。if !(boolean ?? true) { ... }
:(