最近因為專案需求的關係,用了 "iVersion" 這個第三方函式庫
我們的專案是使用 Swift 撰寫,而 iVersion 是一個 Objective-C 的函式庫
在實作 iVersion 的 delegate methods 的時候,這些 Objective-C protocol 中傳入的參數通常會被 Xcode 用 "implicit unwrapping" 這種方式呈現,如下:
func iVersionVersionCheckDidFailWithError(error: NSError!) {
// 對 error 做一些事情
}
因為太信任這個 NSError!
的關係,直接使用 error 這個物件造成正是環境的 App 在檢查版本失敗時多了一些 crash :
一開始在看 log 的時候,本來還以為是 iVersion 的問題,打開 code 看到那個驚嘆後就知道發生了什麼事了
而且 70% 以上的 crash 還是這個看起來不怎麼樣的問題造成的
修改
以這個案例為例,如果要取用 error 的話,就使用 optional 的方式來使用
func iVersionVersionCheckDidFailWithError(error: NSError!) {
// 原本可能長這樣
debugPrint(error.localizedDescription)
// 就可以改成這樣
debugPrint(error?.localizedDescription)
}
即使這個 error 物件非預期的以 nil 值傳入,在使用的時候也不會造成 crash 。
比較實用的情境就是,當要把這個 error 訊息送到 log 服務(如 GA 或 Crashlystic)的時候,就可以不會造成 crash 的送達了
結語
用 ! 在 runtime 是很危險的,
而且這個危險是無法挽回直接會 crash 的
多用 Optional Chaining (?.)
吧!
之前我也有對這個的感想寫過一篇文章: 對 Optional 和 Optional Chaining 的感想
可以再一次參考看看