菜鸟教程小白 发表于 2022-12-11 17:12:41

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


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

<p>再往下,它说的是关于 <code>NS_OPTIONS</code> 标记的 C 样式选项:</p>

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

<p>鉴于 Swift 中没有 <code>options</code> 值类型,我们如何创建一个 C-Style options 变量来使用?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><h1> swift3.0</h1>

<p>几乎与 Swift 2.0 相同。 OptionSetType 被重命名为 OptionSet 并且枚举按惯例写成小写。</p>

<pre><code>struct MyOptions : OptionSet {
    let rawValue: Int

    static let firstOption= MyOptions(rawValue: 1 &lt;&lt; 0)
    static let secondOption = MyOptions(rawValue: 1 &lt;&lt; 1)
    static let thirdOption= MyOptions(rawValue: 1 &lt;&lt; 2)
}
</code></pre>

<p>Swift 3 建议使用空数组文字,而不是提供 <code>none</code> 选项:</p>

<pre><code>let noOptions: MyOptions = []
</code></pre>

<p>其他用法:</p>

<pre><code>let singleOption = MyOptions.firstOption
let multipleOptions: MyOptions = [.firstOption, .secondOption]
if multipleOptions.contains(.secondOption) {
    print(&#34;multipleOptions has SecondOption&#34;)
}
let allOptions = MyOptions(rawValue: 7)
if allOptions.contains(.thirdOption) {
    print(&#34;allOptions has ThirdOption&#34;)
}
</code></pre>

<h1> swift2.0</h1>

<p>在 Swift 2.0 中,协议(protocol)扩展负责处理这些的大部分样板文件,这些样板文件现在作为符合 <code>OptionSetType</code> 的结构导入。 (从 Swift 2 beta 2 开始,<code>RawOptionSetType</code> 已经消失。)声明要简单得多:</p>

<pre><code>struct MyOptions : OptionSetType {
    let rawValue: Int

    static let None         = MyOptions(rawValue: 0)
    static let FirstOption= MyOptions(rawValue: 1 &lt;&lt; 0)
    static let SecondOption = MyOptions(rawValue: 1 &lt;&lt; 1)
    static let ThirdOption= MyOptions(rawValue: 1 &lt;&lt; 2)
}
</code></pre>

<p>现在我们可以通过 <code>MyOptions</code> 使用基于集合的语义:</p>

<pre><code>let singleOption = MyOptions.FirstOption
let multipleOptions: MyOptions = [.FirstOption, .SecondOption]
if multipleOptions.contains(.SecondOption) {
    print(&#34;multipleOptions has SecondOption&#34;)
}
let allOptions = MyOptions(rawValue: 7)
if allOptions.contains(.ThirdOption) {
    print(&#34;allOptions has ThirdOption&#34;)
}
</code></pre>

<h1> swift1.2</h1>

<p>查看由 Swift 导入的 Objective-C 选项(例如 <code>UIViewAutoresizing</code>),我们可以看到选项被声明为符合协议(protocol)的 <code>struct</code> <code>RawOptionSetType</code>,依次符合<code>_RawOptionSetType</code>、<code>Equatable</code>、<code>RawRepresentable</code>、<code>BitwiseOperationsType</code>、和 <code>NilLiteralConvertible</code>。我们可以像这样创建自己的:</p>

<pre><code>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) -&gt; MyOptions { return self(raw) }
    var rawValue: UInt { return self.value }

    static var None: MyOptions { return self(0) }
    static var FirstOption: MyOptions   { return self(1 &lt;&lt; 0) }
    static var SecondOption: MyOptions{ return self(1 &lt;&lt; 1) }
    static var ThirdOption: MyOptions   { return self(1 &lt;&lt; 2) }
}
</code></pre>

<p>现在我们可以处理这个新的选项集 <code>MyOptions</code>,就像 Apple 文档中描述的那样:您可以使用类似 <code>enum</code> 的语法:</p>

<pre><code>let opt1 = MyOptions.FirstOption
let opt2: MyOptions = .SecondOption
let opt3 = MyOptions(4)
</code></pre>

<p>而且它的行为也像我们期望的选项一样:</p>

<pre><code>let singleOption = MyOptions.FirstOption
let multipleOptions: MyOptions = singleOption | .SecondOption
if multipleOptions &amp; .SecondOption != nil {   // see note
    println(&#34;multipleOptions has SecondOption&#34;)
}
let allOptions = MyOptions.fromMask(7)   // aka .fromMask(0b111)
if allOptions &amp; .ThirdOption != nil {
    println(&#34;allOptions has ThirdOption&#34;)
}
</code></pre>

<p>我已经建立了一个 <a href="http://natecook.com/blog/2014/07/swift-options-bitmask-generator/" rel="noreferrer noopener nofollow">generator to create a Swift option set</a>没有所有的查找/替换。 </p>

<p><strong>最新:</strong> Swift 1.1 beta 3 的修改。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何在 Swift 中创建 NS_OPTIONS 样式的位掩码枚举?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/38833030/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/38833030/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何在 Swift 中创建 NS_OPTIONS 样式的位掩码枚举?