(对可选类型的理解可以参见猫神的这篇行走于 Swift 的世界中,在此整理1些关键的部份。)
Swift 中的 Optinal Value 就像是1个盒子,可能装着值,也可能甚么都没装。
我们可以用 ?
定义1个可选类型的整数 :
可选类型的真实身份实际上是 Optional
类型,经常使用的 ?
是 Apple 提供的语法糖。使用 Optional
的写法是这样的:
点进去看下 Optional
的定义:
这样1来,var num: Int? = 3
其实就是 Optional.Some(3)
。
在这里,?
声明了1个 Optional<T>
类型的变量,然后做了判断:
Optional.None
init(_ some: T)
初始化并返回 Optional.Some(T)
。在遭受可选类型的时候,我们可以在 Optional 变量后面加上 !
进行强迫解包。这样虽然减少了代码量,但是容易带来隐患,使用的时候务必要慎重。就像是过马路1样,1定要仔细看好两边车辆,否则悲剧随时可能产生。
而实际上,很多时候可以免使用 !
,用其他方法取而代之。
来看这样1个例子:
在这里先对 ages
进行了排序,然后挑选出年纪小于 50 的人。由于是对字典取值,会出现 nil
,所以 ages[$0]
是 optional 的,需要进行解包。
固然也能够用 if let
:
但是本来1行就可以弄定的问题却拖沓到了5行才解决。实际上,换个思路,我们完全不需要遭受可选类型:
filter
中 $0 表示传入的 key-value ,$0.1 表示 value,map
中 $0 表示传入的 key-value ,$0.0 表示 key 。也许这样可读性比较差,可以通过 tuple 包装1下入参:
在平时的开发中,我们可以用 if let
或 ??
替换掉 !
。如果确切确切肯定不会出问题再去用 !
。
一样是 !
符号,如果放在类型后面,则表示隐式解析可选类型 (Implicitly Unwrapped Optionals):
通过 !
定义的变量,实质上只是对 Optional 的变量多了1层封装,帮我们完成了本来需要手动解包的进程。
在甚么场合下可使用隐式解析可选类型呢?
有些为难的情况,我们想定义常量属性,无奈它的初始化依赖于其他属性值。如果你用可选类型,实在是麻烦,由于你确信无疑它肯定会在调用之前就完成初始化,不多是 nil
,这个时候你可以用 !
进行定义。
举个例子:
这部份内容在 Day11 中有触及,其实更好的方法是用 lazy 延时加载,不再赘述。
隐式解析可选类型仿佛是为了照顾 objc 这个历史包袱而存在。比如 UITableView
中:
我们很清楚的知道,在调用的时候 tableView
和 indexPath
不可能为 nil
,如果还要 if let
这样解包实在是浪费时间。如果是纯洁的 Swift 语言写的,绝对不会定义成 optional 类型。
除上述的情况2 ,其他情况都不该用 (包括情况1)。