如何在Swift中创建NS_OPTIONS样式的位掩码枚举? [英] How to create NS_OPTIONS-style bitmask enumerations in Swift?

查看:300
本文介绍了如何在Swift中创建NS_OPTIONS样式的位掩码枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In Apple's documentation about interacting with C APIs, they describe the way NS_ENUM-marked C-style enumerations are imported as Swift enumerations. This makes sense, and since enumerations in Swift are readily provided as the enum value type it's easy to see how to create our own.

进一步向下,它说这是关于 NS_OPTIONS - 标记的C风格选项:

Further down, it says this about NS_OPTIONS-marked C-style options:


Swift还导入标有 NS_OPTIONS 宏的选项。虽然
选项的行为与导入的枚举类似,但选项也可以
支持一些按位操作,例如& | 。在Objective-C中,
表示一个空的选项集,其常量为零( 0 )。在
Swift中,使用 nil 表示没有任何选项。

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中没有选项值类型,我们如何创建一个C-Style选项变量来使用?

Given that there isn't an options value type in Swift, how can we create a C-Style options variable to work with?

推荐答案

Swift 3.0



几乎与Swift 2.0完全相同。 OptionSetType被重命名为OptionSet,枚举按惯例写成小写。

Swift 3.0

Almost identical to Swift 2.0. OptionSetType was renamed to OptionSet and enums are written lower case by convention.

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)
}

而不是提供 none 选项,Swift 3建议只使用空数组文字:

Instead of providing a none option, the Swift 3 recommendation is to simply use an empty array literal:

let noOptions: MyOption = []

其他用法:

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中,协议扩展会处理大部分样板,现在它们作为符合 OptionSetType 的结构导入。 ( RawOptionSetType 从Swift 2 beta 2开始消失。)声明要简单得多:

Swift 2.0

In Swift 2.0, protocol extensions take care of most of the boilerplate for these, which are now imported as a struct that conforms to OptionSetType. (RawOptionSetType has disappeared as of Swift 2 beta 2.) The declaration is far simpler:

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

Now we can use set-based semantics with 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 ),我们可以看到选项是声明为符合协议 RawOptionSetType struct ,后者又符合 _RawOptionSetType Equatable RawRepresentable BitwiseOperationsType ,和 NilLiteralConvertible 。我们可以像这样创建自己的:

Swift 1.2

Looking at the Objective-C options that were imported by Swift (UIViewAutoresizing, for example), we can see that options are declared as a struct that conforms to protocol RawOptionSetType, which in turn conforms to _RawOptionSetType, Equatable, RawRepresentable, BitwiseOperationsType, and NilLiteralConvertible. We can create our own like this:

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) }
}

现在我们可以处理这个新的选项集, MyOptions ,就像在Apple的文档中描述的那样:你可以使用 enum -like语法:

Now we can treat this new option set, MyOptions, just like described in Apple's documentation: you can use enum-like syntax:

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

它的行为就像我们期望的行为选择:

And it also behaves like we'd expect options to behave:

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")
}

我已经建立了一个生成器来创建一个Swift选项集而没有全部查找/替换。

I've built a generator to create a Swift option set without all the find/replacing.

最新消息: Swift 1.1 beta 3的修改。

Latest: Modifications for Swift 1.1 beta 3.

这篇关于如何在Swift中创建NS_OPTIONS样式的位掩码枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆