Swift: 在开关盒中对可选值进行测试

在 Swift 中,如何在 switch 语句中编写一个 case 来测试在 可以选择内容上切换的值,如果可选的值包含 nil,则跳过 case?

我想这看起来可能是这样的:

let someValue = 5
let someOptional: Int? = nil


switch someValue {
case someOptional:
// someOptional is non-nil, and someValue equals the unwrapped contents of someOptional
default:
// either, someOptional is nil, or someOptional is non-nil but someValue does not equal the unwrapped contents of someOptional
}

如果我只是像这样写它,编译器会抱怨 someOptional没有展开,但是如果我通过在结尾添加 !来显式展开它,那么当 someOptional包含 nil时,我当然会得到一个运行时错误。添加 ?而不是 !对我来说是有意义的(我认为这是出于可选链接的精神) ,但是并不能消除编译器错误(也就是说实际上并不打开可选的)。

50151 次浏览

Optional is just a enum like this:

enum Optional<T> : Reflectable, NilLiteralConvertible {
case none
case some(T)


// ...
}

So you can match them as usual "Associated Values" matching patterns:

let someValue = 5
let someOptional: Int? = nil


switch someOptional {
case .some(someValue):
println("the value is \(someValue)")
case .some(let val):
println("the value is \(val)")
default:
println("nil")
}

If you want match from someValue, using guard expression:

switch someValue {
case let val where val == someOptional:
println(someValue)
default:
break
}

And for Swift > 2.0

switch someValue {
case let val where val == someOptional:
print("matched")
default:
print("didn't match; default")
}

As of Xcode 7, “a new ABC0 pattern can be used to pattern match against optionals as a synonym for .some(x)”. This means that in Swift 2 and later the following variation of rintaro's answer will work as well:

let knownValue = 5


switch someOptional {
case knownValue?:
// Contents of someOptional are knownValue, defined above.
case let otherValue?:
// Contents of someOptional are *any* non-nil value not already tested for.
// Unwrapped contents are assigned to otherValue for use inside this case.
default:
// someOptional is nil.
}

In Swift 4 you can use Optional of Apple to wrappe optional

https://developer.apple.com/documentation/swift/optional

Example

enum MyEnum {
case normal
case cool
}

some

let myOptional: MyEnum? = MyEnum.normal


switch smyOptional {
case .some(.normal):
// Found .normal enum
break


case .none:
break
    

default:
break
}

none

let myOptional: MyEnum? = nil


switch smyOptional {
case .some(.normal):
break


case .none:
// Found nil
break
    

default:
break
}

default

let myOptional: MyEnum? = MyEnum.cool


switch smyOptional {
case .some(.normal):
break


case .none:
break
    

default:
// Found .Cool enum
break
}

Enum with value

enum MyEnum {
case normal(myValue: String)
case cool
}

some value

let myOptional: MyEnum? = MyEnum.normal("BlaBla")


switch smyOptional {
case .some(.normal(let myValue)) where myValue == "BlaBla":
// Here because where find in my myValue "BlaBla"
break
    

// Example for get value
case .some(.normal(let myValue)):
break
    

// Example for just know if is normal case enum
case .some(.normal):
break
    

case .none:
break
    

default:
    

break
}

You can explicitly mention all cases along with nil as an additional case to handle the optional:

switch optionalEnumValue {
case .caseOne:
break
case .caseTwo:
break
case .caseN:
break
case nil:
break
}