ios - 如何在 Swift 中创建 NS_OPTIONS 风格的位掩码枚举?

标签 ios bitwise-operators swift

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

再往下,它是关于 NS_OPTIONS 标记的 C 风格选项的:

Swift also imports options marked with the NS_OPTIONS macro. Whereas options behave similarly to imported enumerations, options can also support some bitwise operations, such as &, |, and ~. In Objective-C, you represent an empty option set with the constant zero (0). In Swift, use nil to represent the absence of any options.

鉴于 Swift 中没有 options 值类型,我们如何创建一个 C 风格的选项变量来使用?

最佳答案

swift 3.0

几乎与 Swift 2.0 相同。 OptionSetType 已重命名为 OptionSet,并且枚举按照惯例写成小写。

struct MyOptions : OptionSet {
    let rawValue: Int

    static let firstOption  = MyOptions(rawValue: 1 << 0)
    static let secondOption = MyOptions(rawValue: 1 << 1)
    static let thirdOption  = MyOptions(rawValue: 1 << 2)
}

Swift 3 建议不提供none 选项,而是简单地使用一个空数组文字:

let noOptions: MyOptions = []

其他用法:

let singleOption = MyOptions.firstOption
let multipleOptions: MyOptions = [.firstOption, .secondOption]
if multipleOptions.contains(.secondOption) {
    print("multipleOptions has SecondOption")
}
let allOptions = MyOptions(rawValue: 7)
if allOptions.contains(.thirdOption) {
    print("allOptions has ThirdOption")
}

swift 2.0

在 Swift 2.0 中,协议(protocol)扩展负责这些的大部分样板文件,它们现在作为符合 OptionSetType 的结构导入。 (RawOptionSetType 从 Swift 2 beta 2 开始就消失了。)声明要简单得多:

struct MyOptions : OptionSetType {
    let rawValue: Int

    static let None         = MyOptions(rawValue: 0)
    static let FirstOption  = MyOptions(rawValue: 1 << 0)
    static let SecondOption = MyOptions(rawValue: 1 << 1)
    static let ThirdOption  = MyOptions(rawValue: 1 << 2)
}

现在我们可以在 MyOptions 中使用基于集合的语义:

let singleOption = MyOptions.FirstOption
let multipleOptions: MyOptions = [.FirstOption, .SecondOption]
if multipleOptions.contains(.SecondOption) {
    print("multipleOptions has SecondOption")
}
let allOptions = MyOptions(rawValue: 7)
if allOptions.contains(.ThirdOption) {
    print("allOptions has ThirdOption")
}

swift 1.2

查看 Swift 导入的 Objective-C 选项(例如 UIViewAutoresizing),我们可以看到选项被声明为符合协议(protocol)的 struct RawOptionSetType,它又符合 _RawOptionSetTypeEquatableRawRepresentableBitwiseOperationsType,和 NilLiteralConvertible。我们可以这样创建自己的:

struct MyOptions : RawOptionSetType {
    typealias RawValue = UInt
    private var value: UInt = 0
    init(_ value: UInt) { self.value = value }
    init(rawValue value: UInt) { self.value = value }
    init(nilLiteral: ()) { self.value = 0 }
    static var allZeros: MyOptions { return self(0) }
    static func fromMask(raw: UInt) -> MyOptions { return self(raw) }
    var rawValue: UInt { return self.value }

    static var None: MyOptions { return self(0) }
    static var FirstOption: MyOptions   { return self(1 << 0) }
    static var SecondOption: MyOptions  { return self(1 << 1) }
    static var ThirdOption: MyOptions   { return self(1 << 2) }
}

现在我们可以像 Apple 文档中描述的那样对待这个新选项集 MyOptions:您可以使用类似 enum 的语法:

let opt1 = MyOptions.FirstOption
let opt2: MyOptions = .SecondOption
let opt3 = MyOptions(4)

它的行为也与我们期望的选项行为一样:

let singleOption = MyOptions.FirstOption
let multipleOptions: MyOptions = singleOption | .SecondOption
if multipleOptions & .SecondOption != nil {     // see note
    println("multipleOptions has SecondOption")
}
let allOptions = MyOptions.fromMask(7)   // aka .fromMask(0b111)
if allOptions & .ThirdOption != nil {
    println("allOptions has ThirdOption")
}

我构建了一个 generator to create a Swift option set没有所有的查找/替换。

最新:对 Swift 1.1 beta 3 的修改。

关于ios - 如何在 Swift 中创建 NS_OPTIONS 风格的位掩码枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38833030/

相关文章:

ios - 显示 UIPopOverPresentationController 时崩溃

ios - NSJSONSerialization 不更新(可能被缓存)

compiler-errors - 字节和位运算符

javascript - 去交错字节

ios - 关闭所有打开的 View Controller 的单一功能

iphone - 使用 UIDocumentInteractionController 处理临时文件

不使用宏定义计算 char 的限制

ios - 将swiftui集成到objective c框架中

ios - responsive/viewport 在浏览器中工作但在 ios 中不工作

ios - 在使用 Alamofire + suggestedDownloadDestination 下载文件之前检查文件是否已经存在