把 swift 升級到 5.0 的時候相信大家一定會遇到建議添加 @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。
延伸閱讀:
- 微博:@沒故事的卓同學
- 掘金博客
- 如果想與我有更密切的交流也可以加入我的知識星球:iOS 程序員保護協會