可空类型
1、可空类型:
代码片段一:
var errorCodeString : String ?
if errorCodeString !=nil {
let theError = errorCodeString!
print(theError)
}
上面的代码,如果省略errorCodeString末尾的感叹号,那就只是把可空的String而不是把实际错误码的String值赋给常量theError。
事实上,errorCodeString的类型是String?
String? 和 String 不是相同的类型——如果有一个String变量,就无法在不展开可空实例的情况下将String?的值赋给这个变量。
2、可空实例绑定:
可空实例绑定(optional binding)是一种固定的模式
代码片段二:
if let temporaryConstant = anOptional {
//使用temporaryConstant
} else {
//anOptional没有值,也就是说anOptional为nil
}
使用可空实例绑定,不在需要强制展开可空实例了,如果转换成功,那么这个操作已经自动完成了。
嵌套可空实例绑定可能会显得错综复杂。如果只是几个可空实例问题不会太大;不过可以想象一下,如果再多几个需要展开的可空实例,这种嵌套会变得多复杂。
幸运的是,单个if let绑定就可以展开多个可空实例
代码片段三:
var errorCodeString : String?
errorCodeString =“404”
if let theError = errorCodeString,let errorCodeInteger = Int(theError){
print(“\(theError):\(errorCodeInteger)”)
}
现在一行代码展开了两个可空实例:let theError = errorCodeString,let errorCodeInteger = Int(theError)。
首先errorCodeString,其值被赋给theError。还用到了Int(theError)尝试把theError转换为nil。因为结果是可空类型,所以需要展开并将其值绑定到errorCodeInteger。
如果两个有任何一个返回nil,那么条件语句的成功代码就不会执行。(注意:不要漏掉代码中的 ,)
3、隐式展开可空类型
代码片段四:
var errorCodeString : String!
errorCodeString =“404”
print(errorCodeString)
注意这里的声明使用的是!,表示这是一个隐式展开可空类型。
代码片段五:
var errorCodeString: String! = nil
let anotherErrorCodeString: String = errorCodeString //能工作吗?
let yetAnotherErrorCodeString = errorCodeString //是可能实例还是隐式展开可空实例呢?
第一个问题的答案会触发陷阱。如果errorCodeString为空,把它赋值给字符串类型的anotherErrorCodeString会导致运行时错误。为什么?
因为anotherErrorCodeString显式声明了类型,不可能是可空实例。
第二个问题,Swift会尽可能推断最安全的类型:普通的可变实例。
yetAnotherErrorCodeString类型会是String?,值为nil。要访问其值,必须展开可空实例,这样有助于增加代码的安全性。
4、nil合并运算符 ??
处理可空类型的一个常见操作是:要么获取其值,要么使用某个默认值
代码片段六:
let description: String
if let errorDescription = errorDescription {
description = errorDescription
}else{
description =“No error”
}
这么写有个问题,那就是需要写很多代码来完成一个本该很简单的操作。 可以使用nil合并运算符
let description = errorDescription ??“No Error”