1. ホーム
  2. ios

[解決済み] SwiftでNS_OPTIONSスタイルのビットマスク列挙を作成する方法とは?

2022-05-17 05:10:55

質問

AppleのC APIとの対話に関するドキュメントでは、以下のように記述されています。 NS_ENUM -マークされた C スタイルの列挙は、Swift の列挙としてインポートされます。これは理にかなっており、Swift での列挙は容易に enum 値型として容易に提供されるので、私たち自身を作成する方法を見るのは簡単です。

さらに下には、次のように書かれています。 NS_OPTIONS -マークされた C スタイルのオプションについてです。

でマークされたオプションもインポートします。 NS_OPTIONS マクロでマークされたオプションもインポートします。一方 オプションはインポートされた列挙型と同様に動作しますが、オプションもまた のようなビット演算もサポートします。 & , | そして ~ . Objective-Cでは では,空のオプション集合を定数ゼロで表します ( 0 ). で Swift では nil を使って、オプションがないことを表します。

がないことを考えると options の値型がないことを考えると、どのようにC-Styleのオプション変数を作成して作業することができるでしょうか?

どのように解決するのですか?

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

を提供する代わりに none オプションを提供する代わりに、Swift 3 の推奨は単に空の配列リテラルを使用することです。

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 では、プロトコル拡張がこれらの定型句のほとんどを引き受けています。 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 など) を見ると、オプションが struct として宣言され、プロトコルに準拠した RawOptionSetType に準拠し、さらに _RawOptionSetType , Equatable , RawRepresentable , BitwiseOperationsType そして 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) }
}

さて、この新しいオプション・セットを扱うことができます。 MyOptions を、Apple のドキュメントに書かれているのと同じように扱うことができます。 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")
}

を構築しました。 ジェネレーターを作り、Swift のオプションセット を生成するためのジェネレーターを作りました。

最新のものです。 Swift 1.1 beta 3に対応した修正。