I could understand that
Enumerations imported using the
NS_ENUMmacro won’t fail when you initialize one with a raw value that does not correspond to an enumeration case. This characteristic facilitates compatibility with C, which allows any value to be stored in an enumeration, including values used internally but not exposed in headers.
However, we should not allow that for NS_CLOSED_ENUM because it is unsafe and causes unexpected crashes.
For example:
typedef NS_ENUM(NSInteger, IntEnum) {
IntEnumZero,
IntEnumOne,
};
Since it is imported as non-frozen enum so I have to handle @unknown default anyway.
if let ie = IntEnum(rawValue: 100) {
switch ie {
case .zero:
print("zero")
case .one:
print("one")
@unknown default:
print("unknown")
}
}
However, if I define it as NS_CLOSED_ENUM
typedef NS_CLOSED_ENUM(NSInteger, IntEnum) {
IntEnumZero,
IntEnumOne,
};
It should be imported as frozen enum and only those raw values declared in the enum definition should convert successfully to the enum. Unfortunately, that’s not the case and it causes crash:
if let ie = IntEnum(rawValue: 100) {
switch ie {
case .zero:
print("zero")
case .one: // Thread 1: Fatal error: unexpected enum case 'IntEnum(rawValue: 100)'
print("one")
}
}
I believe it is a bug and filed here: Imported enum from NS_CLOSED_ENUM shouldn't allow arbitrary raw value · Issue #85701 · swiftlang/swift · GitHub