Swift 5.0 值得關注的特性:Handle unknown values using "@unknown default"

沒故事的卓同學發表於2019-04-20

把 swift 升級到 5.0 的時候相信大家一定會遇到建議新增 @unknown default 的警告:

Swift 5.0 值得關注的特性:Handle unknown values using "@unknown default"

@unknown default 解決的兩個問題

未來增加新的 case 後不會影響原有程式碼的編譯

如果 switch 語句中覆蓋了列舉的每個 case,那麼未來這個列舉如果增加了一個值,一定會對原來呼叫的程式碼造成 break change。如果是我們自己定義的列舉還好改,如果是系統級的庫就會造成很大的影響。大概也是考慮到 swift 5.0 開始 ABI 穩定的承諾,引入 @unknown default 對未來列舉的擴充套件新值時保證相容性提供了很好的支援。

在有新的列舉值時編譯器可以提醒

如果在 switch 語句中使用了 default,如果未來新增了列舉值也不會破壞到呼叫程式碼的編譯。但是使用者會很難發現有新的列舉選項產生了。Apple 舉了一個 UIKeyboardType 的例子,這已經是一個非常早期就存在的列舉,但是在 iOS 10 中還是新增了 asciiCapableNumberPad了這個選項。iOS 每個版本升級底層都會增加了一些功能,使用@unknown default 標記在 switch 語句中,如果有新的列舉值編譯器就可以很好的提示使用者有新的 case 需要處理。

Frozen enum

有些列舉未來可能會變動,有些在宣告的時候就很確定不會改變。這種狀態 apple 稱之為 frozen。列舉有兩種可能:frozen(不變的)和 non-frozen(值會變的)。原來 OC 中的所有列舉預設都認為是 non-frozen 的。 如果想要把列舉宣告為 non-frozen,使用 NS_CLOSED_ENUM 宣告:

typedef NS_CLOSED_ENUM(NSInteger, NSComparisonResult) {
  NSOrderedAscending = -1L,
  NSOrderedSame,
  NSOrderedDescending
};
複製程式碼

影響範圍

目前 @unknown default 只針對 C 風格的 enum 和 Foundation 中的列舉起作用,使用者在 swift 自定義的列舉都認為是 frozen 的。 我也不是很理解為什麼這個列舉的型別區分只支援 OC,swift 不支援。這個特性如果被社群接受的話,猜測 swift 在未來版本也會支援使用者自定義的 swift 列舉也可以標記為 non-frozen。


延伸閱讀:


相關文章