Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 检查可选布尔值_Swift_Boolean_Optional - Fatal编程技术网

Swift 检查可选布尔值

Swift 检查可选布尔值,swift,boolean,optional,Swift,Boolean,Optional,当我想检查可选布尔值是否为真时,这样做行不通: var boolean : Bool? = false if boolean{ } 它会导致以下错误: 可选类型“@IvalueBool?”不能用作布尔值;测试'!=零 反而 我不想检查零;我想检查返回的值是否为真 如果布尔值==true,我是否总是必须执行如果我使用可选布尔值 既然Optionals不再符合BooleanType,编译器难道不知道我想检查Bool的值吗?对于可选booleans,需要明确检查: if boolean == tru

当我想检查可选布尔值是否为真时,这样做行不通:

var boolean : Bool? = false
if boolean{
}
它会导致以下错误:

可选类型“@IvalueBool?”不能用作布尔值;测试'!=零 反而

我不想检查零;我想检查返回的值是否为真

如果布尔值==true,我是否总是必须执行
如果我使用可选布尔值


既然Optionals不再符合
BooleanType
,编译器难道不知道我想检查Bool的值吗?

对于可选booleans,需要明确检查:

if boolean == true {
    ...
}
否则,您可以展开可选的:

if boolean! {
    ...
}
但如果布尔值为
nil
,则会生成一个运行时异常,以防止:

if boolean != nil && boolean! {
    ...
}
在beta 5之前,这是可能的,但正如发行说明中所述,它已被更改:

Optionals在有值时不再隐式计算为true,没有值时不再隐式计算为false,以避免在使用可选Bool值时出现混淆。相反,使用==或!=对nil进行显式检查运算符以确定可选项是否包含值

附录:正如@MartinR所建议的,第三个选项更紧凑的变化是使用凝聚运算符:

if boolean ?? false {
    // this code runs only if boolean == true
}
这意味着:如果布尔值不是nil,则表达式计算为布尔值(即使用未包装的布尔值),否则表达式计算为
false

可选绑定 斯威夫特3号和4号 Swift 2.2 如果
booleanValue
nil
,则代码
let booleanValue=booleanValue
返回
false
if
。如果
booleanValue
不是
nil
,则此代码定义一个名为
booleanValue
Bool
类型的新变量(而不是可选的
Bool?

Swift 3&4代码
booleanValue
(和Swift 2.2代码
,其中booleanValue
)评估新的
booleanValue:Bool
变量。如果为true,则执行
If
块时,作用域中新定义的
booleanValue:Bool
变量(允许选项在
If
块中再次引用绑定值)

注意:Swift惯例是将绑定常量/变量命名为与可选常量/变量相同的名称,例如
let booleanValue=booleanValue
。这种技术称为可变阴影。您可以打破惯例,使用类似于
让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!布尔值??false不编译

强制展开可选(避免) 强制展开会增加将来有人进行更改的可能性,该更改会编译但在运行时崩溃。因此,我会避免这样的事情:

var booleanValue : Bool? = false
if booleanValue != nil && booleanValue! {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

一般方法 尽管此堆栈溢出问题特别询问如何检查
if
语句中的
Bool?
是否为
true
,但确定检查true、false还是将未包装值与其他表达式组合的一般方法是很有帮助的


随着表达式变得越来越复杂,我发现可选绑定方法比其他方法更灵活、更容易理解。请注意,可选绑定适用于任何可选类型(
Int?
String?
,等等)。

我找到了另一种解决方案,重载布尔运算符。例如:

public func < <T: Comparable> (left: T?, right: T) -> Bool {
    if let left = left {
        return left < right
    }
    return false
}
public func<(左:T?,右:T)->Bool{
如果让左=左{
返回左<右
}
返回错误
}

这可能并不完全符合语言变化的“精神”,但它允许安全地展开选项,并且可以在任何地方使用条件语句,包括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
}
如前所述

Optionals在有值时不再隐式计算为true,没有值时不再隐式计算为false,以避免在使用可选Bool值时出现混淆。相反,使用==或!=对nil进行显式检查运算符以确定可选项是否包含值

我花了几个小时试图理解我偶然发现的一行代码,但这条线索使我走上了正确的轨道

这段引语来自,从那以后,苹果推出了以下内容,而后者使其符合

现在可以使用
从不?
检查布尔值是否为
nil


var boolean: Bool? = false
boolean is Never? // false
boolean = true
boolean is Never? // false
boolean = nil
boolean is Never? // 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
也可以。第三个选项的变体,使用“nil合并运算符”:
if boolean??false{…}
。但是如果我想否定它,它开始看起来很可笑:
如果!(布尔值??真){…}
:(强制展开是一个非常糟糕的主意。应该始终避免。第一个选项有什么问题?对我来说,这似乎是最好的方法。我很难使用带有可选for while循环的布尔表达式。nil coalescing操作符可以工作,但它混乱且容易出错。如果let
,有没有办法使用
?@jbaraga,请发布。)您想知道的while循环的一个示例。在将数组用作堆栈时,我希望弹出值,直到满足条件或堆栈为空。例如,
while array.last
您可以使用<
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")
}

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

@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"