Skip to content

NS_CLOSED_ENUM

ShenYj edited this page Feb 23, 2022 · 1 revision

NS_CLOSED_ENUM

用于声明不会变更枚举成员的简单的枚举(简称 “冻结枚举” ),对应 Swift 中的 @frozen 关键字,将作为 @frozen enum 导入到 Swift 中。冻结枚举对于希望在 switch 语句中匹配有限状态集的时候非常有用,这个有限状态集是一个完整的集合,覆盖了所有情况,将来不会再有其他新的情况。 例如,NSComparisonResult 枚举用于指定如何排序,在两个数比大小时,无非就 <、=、> 三种情况,所以非常适合使用冻结枚举。

// Declare in Objective-C
typedef NS_CLOSED_ENUM(NSInteger, NSComparisonResult) {
    NSOrderedAscending = -1L,
    NSOrderedSame,
    NSOrderedDescending
};

// In Swift, the NSComparisonResult enumeration is imported like this:
@frozen enum NSComparisonResult : Int {
    case orderedAscending = -1
    case orderedSame = 0
    case orderedDescending = 1
}

使用 NS_ENUMNS_CLOSED_ENUM 枚举宏在导入到 Swift 时生成的是实际 enum 类型,而其它枚举宏都是生成 struct 类型。

相比较于非冻结枚举,冻结枚举降低了灵活性,但提升了性能。一旦枚举被标记为冻结枚举,那么在未来版本的库中就不能通过添加、删除或重新排序枚举的 case,否则会破坏 ABI 兼容性。

Swift 中的 default 与 @unknown default

  • 对于非冻结枚举,你需要使用 default 或者 @unknown default 来处理未知的 case(未来可能新增枚举类型),否则会得到编译器警告 Switch covers known cases, but 'enumType' may have additional unknown values,但 Xcode 的 fix 方案是使用 @unknown default

  • 而对于冻结枚举,使用 @unknown default 无论如何都会得到编译器警告(能运行)。

    • 如果你穷举了所有 case,将得到警告 Default will never be executed,因为冻结枚举已经约定好将来不会添加新的枚举成员,所以 @unknown default case 永远不会执行。虽然这里使用 default 不会得到警告,但也是不会执行的

    • 如果你没有穷举所有 case,将得到警告 Switch must be exhaustive -> 使用 @unknown default 必须穷举所有 case

  • 对于冻结枚举,如果不希望穷举所有 case, 还是可以使用 default,区别于 @unknown default, 不会得到编译警告

简单来说 default@unknown default 都可以用来处理已知以及未知的情况。

区别在于,使用 @unknown default,如果你没有穷举所有枚举类型,或者未来有新增枚举类型,那么编译器会给出警告提示。

对于非冻结枚举,如果你想穷举所有 case,并希望未来有新增枚举类型时得到编译器警告,那么就使用 @unknown default
也就是说,@unknown default 应该只匹配未来加入的枚举 case

Handling Future Enum Cases

Getting Started

Social

Clone this wiki locally