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

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

问题描述

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

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

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

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

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

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

斯威夫特 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")
}

斯威夫特 1.2

查看Swift引入的Objective-C选项(例如UIViewAutoresizing),我们可以看到options被声明为一个符合协议的structRawOptionSetType,依次符合_RawOptionSetTypeEquatableRawRepresentableBitwiseOperationsType,和 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 的语法:

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天全站免登陆