(對可選類型的理解可以參見貓神的這篇行走于 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)。