LoginSignup
45
42

More than 5 years have passed since last update.

OptionSetType

Swift2.0で新しくOptionSetTypeプロトコルが導入され、
簡単にOptionSetを定義できるようになりました。

Sample

今回はUInt8型とし、最大8個のオプションを定義できるようにします。

CountryOption.swift
struct CountryOption: OptionSetType {

    let rawValue: UInt8
    init(rawValue: UInt8) { self.rawValue = rawValue }

    // それぞれの桁にオプションを定義
    static let Japan         = CountryOption(rawValue: 0b00000001)
    static let UnitedStates  = CountryOption(rawValue: 0b00000010)
    static let UnitedKingdom = CountryOption(rawValue: 0b00000100)
    static let China         = CountryOption(rawValue: 0b00001000)
    static let France        = CountryOption(rawValue: 0b00010000)
    static let Australia     = CountryOption(rawValue: 0b00100000)
    static let India         = CountryOption(rawValue: 0b01000000)
    static let Canada        = CountryOption(rawValue: 0b10000000)
    static let All           = CountryOption(rawValue: 0b11111111)

    // 値のグループをオプションとして定義することもできる。
    static let Asia        : CountryOption = [.Japan, .China, .India]
    static let Europe      : CountryOption = [.UnitedKingdom, .France]
    static let NorthAmerica: CountryOption = [.UnitedStates, .Canada]
}

contains

値が含まれるかどうかを判定する。

let europe: CountryOption = .Europe
europe.contains(.France) // true
europe.contains(.India)  // false

insert, remove

var wishToGo: CountryOption = [.India, .UnitedStates, .UnitedKingdom, .France]

insert
新しくオプションを追加する。

wishToGo.insert(.China)
// wishToGo = [.India, .UnitedStates, .UnitedKingdom, .France, .China]

remove
オプションを取り除き、取り除いたものを返す。
指定したものを含んでいなかった場合はnilを返す。
※説明が難しいのでコードを見てください。

let removed1 = wishToGo.remove(.UnitedStates)      // removed1 = .UnitedStates
let removed2 = wishToGo.remove([.Canada, .France]) // removed2 = nil
// wishToGo = [.India, .UnitedKingdom, .China]

exclusiveOr, exclusiveOrInPlace → XOR演算

exclusiveOrは共通部分を除いたものを返す。
exclusiveOrInPlaceは演算結果で書き換える。

Exclusive.png

var pacific : CountryOption = [.UnitedStates, .China, .Japan, .Australia, .Canada]
let atlantic: CountryOption = [.UnitedStates, .UnitedKingdom, .France, .Canada]

let either = pacific.exclusiveOr(atlantic)
// either = [.China, .Japan, .Australia, .UnitedKingdom, .France]

intersect, intersectInPlace → AND演算

intersectは共通部分を返す。
intersectInPlaceは演算結果で書き換える。

Intersect.png

var pacific : CountryOption = [.UnitedStates, .China, .Japan, .Australia, .Canada]
let atlantic: CountryOption = [.UnitedStates, .UnitedKingdom, .France, .Canada]

let both = pacific.intersect(atlantic)
// both = [.UnitedStates, .Canada]

union, unionInPlace → OR演算

unionは要素を合わせたものを返す。
unionInPlaceは演算結果で書き換える。

Union.png

var visited: CountryOption = [.Japan, .China, .UnitedStates]
visited.unionInPlace([.France, .Australia])
// visited = [.Japan, .China, .UnitedStates, .France, .Australia]

結果の通り、insertとunionInPlaceは同じです。

出力

そのままだと出力が不便。

print(CountryOption.Asia) // "CountryOption(rawValue: 73)"

文字列で出力するよう拡張。

extension CountryOption: CustomStringConvertible {
    var description: String {
        let strings = ["日本", "アメリカ", "イギリス", "中国", "フランス", "オーストラリア", "インド", "カナダ"]
        var members = [String]()
        for (flag, string) in strings.enumerate() where self.contains(CountryOption(rawValue: 1 << (UInt8(flag)))) {
            members.append(string)
        }
        return members.description
    }
}
print(CountryOption.Asia) // "["日本", "中国", "インド"]"

参考

Swift Standard Library Reference
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Reference/Swift_OptionSetType_Protocol/index.html#//apple_ref/swift/intfm/OptionSetType/s:FeRq_Ss13OptionSetTypezq_qq_S_7Element_SsS_6removeuRq_S_zq_qq_S_7Element_FRq_Fqq_S_7ElementGSqqq_S_7Element_

Swift 2.0 の新しいOption、OptionSetType
http://www.toyship.org/archives/2208

Notes from WWDC 2015: The Enumerated Delights of Swift 2.0 Option Sets
http://www.informit.com/articles/article.aspx?p=2420231

おわりに

便利になったOptionSetを使って今度はUIViewに枠線をつけたいと思います!

45
42
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
42