如何在Swift中创建NS_OPTIONS样式的位掩码枚举?

在Apple有关与C API交互的文档中,他们描述了将NS_ENUM标记的C样式枚举作为Swift枚举导入的方式。这是有道理的,并且由于Swift中的枚举很容易作为enum值类型提供,因此很容易看到如何创建我们自己的枚举。


再往下,它说了关于NS_OPTIONS标记C样式的选项:


Swift还会导入标有NS_OPTIONS宏的选项。而选项的行为类似于进口枚举,选项还可以支持一些位操作,如&,|和~。在Objective-C中,您表示一个常量为零(0)的空选项集。在Swift中,用于nil表示没有任何选项。


鉴于optionsSwift中没有值类型,我们如何创建要使用的C-Style选项变量?


墨色风雨
浏览 898回答 3
3回答

隔江千里

斯威夫特3.0与Swift 2.0几乎相同。OptionSetType重命名为OptionSet,并且按惯例将枚举写为小写。struct MyOptions : OptionSet {&nbsp; &nbsp; let rawValue: Int&nbsp; &nbsp; static let firstOption&nbsp; = MyOptions(rawValue: 1 << 0)&nbsp; &nbsp; static let secondOption = MyOptions(rawValue: 1 << 1)&nbsp; &nbsp; static let thirdOption&nbsp; = MyOptions(rawValue: 1 << 2)}noneSwift 3建议不要提供选项,而只是使用空数组文字:let noOptions: MyOptions = []其他用法:let singleOption = MyOptions.firstOptionlet multipleOptions: MyOptions = [.firstOption, .secondOption]if multipleOptions.contains(.secondOption) {&nbsp; &nbsp; print("multipleOptions has SecondOption")}let allOptions = MyOptions(rawValue: 7)if allOptions.contains(.thirdOption) {&nbsp; &nbsp; print("allOptions has ThirdOption")}斯威夫特2.0在Swift 2.0中,协议扩展会处理大多数样板文件,这些样板文件现在已作为符合的结构导入OptionSetType。(RawOptionSetType自Swift 2 beta 2起已消失。)声明要简单得多:struct MyOptions : OptionSetType {&nbsp; &nbsp; let rawValue: Int&nbsp; &nbsp; static let None&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= MyOptions(rawValue: 0)&nbsp; &nbsp; static let FirstOption&nbsp; = MyOptions(rawValue: 1 << 0)&nbsp; &nbsp; static let SecondOption = MyOptions(rawValue: 1 << 1)&nbsp; &nbsp; static let ThirdOption&nbsp; = MyOptions(rawValue: 1 << 2)}现在我们可以使用基于集合的语义MyOptions:let singleOption = MyOptions.FirstOptionlet multipleOptions: MyOptions = [.FirstOption, .SecondOption]if multipleOptions.contains(.SecondOption) {&nbsp; &nbsp; print("multipleOptions has SecondOption")}let allOptions = MyOptions(rawValue: 7)if allOptions.contains(.ThirdOption) {&nbsp; &nbsp; print("allOptions has ThirdOption")}斯威夫特1.2看着由夫特导入的(Objective-C的选项UIViewAutoresizing,例如),我们可以看到,选项被声明为struct符合协议RawOptionSetType,这反过来又符合&nbsp; _RawOptionSetType,Equatable,RawRepresentable,BitwiseOperationsType,和NilLiteralConvertible。我们可以这样创建自己的:struct MyOptions : RawOptionSetType {&nbsp; &nbsp; typealias RawValue = UInt&nbsp; &nbsp; private var value: UInt = 0&nbsp; &nbsp; init(_ value: UInt) { self.value = value }&nbsp; &nbsp; init(rawValue value: UInt) { self.value = value }&nbsp; &nbsp; init(nilLiteral: ()) { self.value = 0 }&nbsp; &nbsp; static var allZeros: MyOptions { return self(0) }&nbsp; &nbsp; static func fromMask(raw: UInt) -> MyOptions { return self(raw) }&nbsp; &nbsp; var rawValue: UInt { return self.value }&nbsp; &nbsp; static var None: MyOptions { return self(0) }&nbsp; &nbsp; static var FirstOption: MyOptions&nbsp; &nbsp;{ return self(1 << 0) }&nbsp; &nbsp; static var SecondOption: MyOptions&nbsp; { return self(1 << 1) }&nbsp; &nbsp; static var ThirdOption: MyOptions&nbsp; &nbsp;{ return self(1 << 2) }}现在,我们可以像对待MyOptions苹果文档中所述的那样对待这个新的选项集:您可以使用enum-like语法:let opt1 = MyOptions.FirstOptionlet opt2: MyOptions = .SecondOptionlet opt3 = MyOptions(4)而且它的行为也像我们期望的选项那样:let singleOption = MyOptions.FirstOptionlet multipleOptions: MyOptions = singleOption | .SecondOptionif multipleOptions & .SecondOption != nil {&nbsp; &nbsp; &nbsp;// see note&nbsp; &nbsp; println("multipleOptions has SecondOption")}let allOptions = MyOptions.fromMask(7)&nbsp; &nbsp;// aka .fromMask(0b111)if allOptions & .ThirdOption != nil {&nbsp; &nbsp; println("allOptions has ThirdOption")}我已经构建了一个生成器来创建Swift选项集,而无需进行所有查找/替换。最新:对Swift 1.1 beta 3的修改。

守候你守候我

Xcode 6.1 Beta 2对RawOptionSetType协议进行了一些更改(请参阅此Airspeedvelocity博客条目和Apple发行说明)。基于Nate Cooks的示例,这里是更新的解决方案。您可以这样定义自己的选项集:struct MyOptions : RawOptionSetType, BooleanType {&nbsp; &nbsp; private var value: UInt&nbsp; &nbsp; init(_ rawValue: UInt) { self.value = rawValue }&nbsp; &nbsp; // MARK: _RawOptionSetType&nbsp; &nbsp; init(rawValue: UInt) { self.value = rawValue }&nbsp; &nbsp; // MARK: NilLiteralConvertible&nbsp; &nbsp; init(nilLiteral: ()) { self.value = 0}&nbsp; &nbsp; // MARK: RawRepresentable&nbsp; &nbsp; var rawValue: UInt { return self.value }&nbsp; &nbsp; // MARK: BooleanType&nbsp; &nbsp; var boolValue: Bool { return self.value != 0 }&nbsp; &nbsp; // MARK: BitwiseOperationsType&nbsp; &nbsp; static var allZeros: MyOptions { return self(0) }&nbsp; &nbsp; // MARK: User defined bit values&nbsp; &nbsp; static var None: MyOptions&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { return self(0) }&nbsp; &nbsp; static var FirstOption: MyOptions&nbsp; &nbsp;{ return self(1 << 0) }&nbsp; &nbsp; static var SecondOption: MyOptions&nbsp; { return self(1 << 1) }&nbsp; &nbsp; static var ThirdOption: MyOptions&nbsp; &nbsp;{ return self(1 << 2) }&nbsp; &nbsp; static var All: MyOptions&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ return self(0b111) }}然后可以像这样使用它来定义变量:let opt1 = MyOptions.FirstOptionlet opt2:MyOptions = .SecondOptionlet opt3 = MyOptions(4)像这样测试位:let singleOption = MyOptions.FirstOptionlet multipleOptions: MyOptions = singleOption | .SecondOptionif multipleOptions & .SecondOption {&nbsp; &nbsp; println("multipleOptions has SecondOption")}let allOptions = MyOptions.Allif allOptions & .ThirdOption {&nbsp; &nbsp; println("allOptions has ThirdOption")}
打开App,查看更多内容
随时随地看视频慕课网APP