本文原载于我的博客:https://www.seekingmini.top/archives/swift踩坑可空类型
写在前面
Swift是一门非常安全的语言…
可空类型
什么是可空类型
可空类型(optional)是Swift的独特特性,用来定某个实例可能没有值。如果一个实例没有值,就称其为nil。
举例
var n1: Int?
print(n1)
var n2: Int
print(n2)
以上代码两者打印的结果不同,n1
的打印结果为nil
,而n2
的打印结果为0
。在声明变量n1
时在后面加了一个?
表示其成为可空类型变量。我们希望知道的是变量何时为nil
,以相应地执行一些代码。在这种情况下,可以使用条件语句来对变量的值做到这一点。
var n1: Int?
n1 = 1
print(n1)
if n1 != nil {
let n2 = n1!
print(n2)
}
n1
的打印结果为Optional(1)
,n2
的打印结果为1
。两者打印的结果不同是因为在声明n2
时n1
后面加了一个!
表示强制展开(forced unwrapping)。强制展开会强制访问可空实例封装的值,也就是说,如果n1
为空,使用强制展开就会产生运行时错误。
特别说明:强制展开有一定的危险性。如果可空实例没有值,程序会在运行时触发陷阱。
可空实例绑定
如果有值,就将其赋给一个临时常量或变量,并且使这个常量或变量在条件语句的第一个分支代码中可用。
语法格式
if let tmp = optional {
// 使用tmp做一个事情
} else {
// optional为nil
}
举例
var n1: Int?
if let n2 = n1 {
print(n2)
} else {
print("空")
}
以上代码打印结果为空
,因为n1
是可空实例且为空,所以不会调用if
分支的代码而是调用else
分支的代码。这样有一个好处就是不需要强制展开可空实例,减少陷阱的触发。
可空链式调用
可空链式调用允许我们把多个查询串联为一个可空实例的值。如果链式调用中的每个可空实例都包含值,那么每个调用都会成功,整个查询会返回期望类型的可空实例。如果查询链中的任意可空实例是
nil
,那么整个式调用会返回nil
。
举例
var n1: Int?
n1 = 200
var description: String?
if let n2 = n1, n2 == 200 {
description = "Success."
}
print(description?.uppercased())
以上代码打印结果为Optional("SUCCESS.")
。if
分支首先会判断n1
是否为空,再判断n2
的值是否为200
。
nil合并运算符
处理可空类型时的一个常见动作时是:要么获取其值(如果可实例有值),要么使用某个默认值(如果可实例是
nil
)。可以用nil合并运算符(nil coalescing operator)??
来到这个目的。
举例
var n1: Int?
n1 = 666
let n2: Int = n1 ?? 0
print(n2)
以上代码打印结果为666
。
总结
可空类型最好用来表示本来就可以为空的概念,即适合用来表示缺失某些东西的场景。但是缺失不等于零。例如:一个人养了一只宠物狗,其名字就可以为空(只是举个例子而已…);而一个人的银行账户余如果为空就需要用零来表示。