Swift中OptionSet能否包含64个以上成员?是否有解决办法?
关于Swift OptionSet超过64个成员的限制问题
你观察到的现象并非OptionSet本身的固有限制,而是rawValue所使用的整数类型的位数限制导致的。
问题原因
默认情况下你用Int作为OptionSet的rawValue类型:
- 在64位系统中,
Int是64位有符号整数,其有效位范围是0到62位(第63位是符号位)。 - 当执行
1 << 64或1 << 65时,会触发整数溢出,结果被截断为0,导致多个选项共享同一个rawValue,最终contains判断出错。
示例代码(问题复现)
struct Options: OptionSet { let rawValue: Int static let options0 = Options(rawValue: 1 << 0) static let options1 = Options(rawValue: 1 << 1) // ... 省略中间选项 static let options63 = Options(rawValue: 1 << 63) // rawValue = 0,溢出导致 static let options64 = Options(rawValue: 1 << 64) // rawValue = 0,溢出导致 static let options65 = Options(rawValue: 1 << 65) } let options: Options = [.options64] precondition(!options.contains(.options65)) // 触发断言失败,因为两者rawValue都是0
解决办法
通过更换rawValue的整数类型,即可支持更多选项:
- 如果需要64个成员:改用
UInt64作为rawValue类型。UInt64是64位无符号整数,有效位范围是0到63位,刚好支持64个独立选项。 - 如果需要超过64个成员:使用
UInt128(Swift 5.5+支持),它能提供128位无符号整数空间,支持最多128个独立选项。 - 极端需求(超过128个成员):自定义符合
BinaryInteger协议的大整数类型,实现更大位数的支持。
修复后的示例代码
struct Options: OptionSet { let rawValue: UInt128 static let options0 = Options(rawValue: 1 << 0) static let options1 = Options(rawValue: 1 << 1) // ... 省略中间选项 static let options63 = Options(rawValue: 1 << 63) static let options64 = Options(rawValue: 1 << 64) static let options65 = Options(rawValue: 1 << 65) } let options: Options = [.options64] precondition(!options.contains(.options65)) // 断言成功,判断正确
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

