引言
最近有幸參加公司的iOS招聘面試祈秕,發(fā)現很多3年左右工作經驗的工程師對 swift 還停留在想要去了解的階段肠槽,一些是由于公司項目的原因,一些是因為個人原因姑荷,但 swift 4.0 都已經出了耐量,還在抱著觀望的心態(tài)實在不像一個做技術的人應有的態(tài)度飞蚓,所以最近想寫一些跟 swift 相關的知識點,既作為自己對知識點的整理和保存廊蜒,也希望能幫助到一些正在學習 swift 的小伙伴~~~
概念
空合運算符趴拧,當然這個運算符并不是 swift 首創(chuàng),早在 C#山叮,Perl著榴,PHP7.0.0 等均有此運算符。
作用
這是一個非常有用而且常用的操作符屁倔,可以用來快速對 nil 進行條件判空脑又,使代碼看起來更加簡潔。
- 使用之前
// 寫法一:可選綁定(Optional Binding)
var username = ""
if let name = inputName {
username = name
} else {
username = "Guest"
}
// 寫法二:三目運算符(ternary operator)
let username = inputName != nil ? inputName! : "Guest"
- 使用之后
let username = inputName ?? "Guest"
事實上 a ?? b 表示將對可選類型a進行為空判斷锐借,如果a包含一個值问麸,就進行解封,否則就返回一個默認值b钞翔。
注意:表達式 a 必須是 Optional 類型严卖。默認值 b 的類型必須要和 a 存儲值的類型保持一致。
定義
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
- @autoclosure
@autoclosure作用就是把一句表達式自動地封裝成一個閉包布轿,@autoclosure并不支持帶有輸入參數的寫法哮笆,只能使用類似 () -> T 的參數才能使用這個特性俺亮。所以寫接受 @autoclosure 的方法時還需謹慎,在容易產生誤解的時候疟呐,還是建議使用完整的閉包。
了解了 @autoclosure 之后 我們來猜一下 ?? 的實現
- 實現
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T {
switch optional {
case .Some(let value):
return value
case .None:
return defaultValue()
}
}
到這里我想除了 ?? 的實現之外东且,對 Optional 的實現應該也有所了解了
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
init()
init(_ some: T)
...
}
當 Optional 沒有值時启具,返回的 nil 其實就是 Optional.None,即沒有值珊泳。除了 None 以外鲁冯,還有一個 Some,當有值時就是被 Some(T) 包裝的真正的值色查,所以拆包其實就是將Some里面的值取出來薯演。
可能有些朋友會有疑問為什么這里要使用 @autoclosure,直接將 T 作為參數返回不行嗎秧了?這正是 @autoclosure 一個最值得稱贊的地方跨扮。如果我們直接使用 T,那么意味著 ?? 操作符真正取值之前验毡,我們就必須準備好一個默認值衡创,這個默認值的準備和計算會降低性能。但如果 optional 不是 nil晶通,就完全不需要這個默認值璃氢,會直接返回 optional 解包后的值。這種情況下默認值的準備就屬于過度開銷了狮辽。使用 @autoclosure 就是將默認值的計算推遲到 optional 確定為 nil 之后一也。