Swift 中 Optional 总结

在Swift之前,程序中表示变量无值,值类型,一般是用一个初始值,像 Int 0。但 0 本身也是有意义的,它不能很完美的表示值不存在。ObjC中用NULL,nil 表示为空,但使用起来很不安全。

可能值类型 语法

Optional 是Swift中一个很大的亮点,它添加了一种新的可能值类型,专门用于处理没有值的情况,让语言更符合现实世界。Optional 表示为:

  • 有值,等于 x
  • 或者没有值 nil
1
2
3
var optionalNumber: Int?
// 默认值 为nil, OC中nil 表示指针为空。Swift中nil表示没有值
// 非可能值类型

可能值 内部结构

其内部就是一个枚举。

1
2
3
4
enum Optional<T> {
case None
case Some(T)
}

Non-Optional Types(非可能值类型)

在定义变量时,如果类型后面不加问号,则表示类型为非可能值类型。该变量不能设为空,一定要在init时进行显示赋值。

可能值与初始化

可能值在类中,不需要构造器中进行初始化,而非可能值则强制要求在构造器中完成初始化(属性定义时赋值,是一种快捷方式)。

判断有没有值

1
2
if (a == nil) {
}

Swift 1.0 进行了更新,可能值不再隐形为true false,判断是否有值时要用 a != nil

强制拆包

使用强制拆包时,一定要确定有值,不然会引发Crash,所以要用if来确保,逻辑要求。

1
2
3
4
5
var name: String?
if (name != nil) {
println(name!)
}

隐式解析 ImplicitlyUnwrappedOptional

如果你知道一个可能值类型一定有值的情况下,每次使用 if 来判断显得很low。这时的状态被定义为隐式解析可选类型(implicitly unwrapped optionals)

1
2
3
4
5
6
7
8
var name: String!
init() {
// 这种形式不强制在init中进行初始化
// 使用时不需要感叹号进行拆包
println(name)
}

Optional Binding (可能值绑定)

每次进行拆包时都要判定,很繁琐,可以通过 Optional Binding来简化操作(检测的同时拆包)。可用来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。

可能值绑定可以用在 if 和 while 语句中。

1
2
3
if let someValue = someOptioanl {
let newValue = someValue //不用再强制解包了
}

Q: 如何对多个可能值同时进行可能值绑定?

1
2
3
4
5
6
7
8
9
10
// 表达式中要对2个可能值进行运算,这样写是有问题的。
var canGoBack: Bool = (self.wkWebView?.canGoBack || self.uiWebView?.canGoBack)
// 现在只能这样写,不知有没有更好写法。
var canGoBack: Bool!
if let wkWebView = self.wkWebView {
if let uiWebView = self.uiWebView {
canGoBack = wkWebView.canGoBack || uiWebView.canGoBack
}
}

Optional Chaining(可能值链)

简洁方式处理一串可能值。这些值有着层级关系。

1
2
3
4
// 如果其中一个出现nil,直接返回nil,不再向下继续。
if let addressNumber = a.residence?.address?.buildingNumber?.toInt() {
// statement
}

总结

在开始学习Swift时,感觉每个值都要进行一次判断,多一层操作,很繁琐。

用多了后,开始感受到更多的是安全。不需要大量的try/catch 来进行异常捕获,因为大部分的异常都是类型转换,值不存在所引发了。而这些都被Optional所解决了。

REF::