OptionSetType
Swift2.0で新しくOptionSetTypeプロトコルが導入され、
簡単にOptionSetを定義できるようになりました。
Sample
今回はUInt8型とし、最大8個のオプションを定義できるようにします。
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は演算結果で書き換える。
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は演算結果で書き換える。
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は演算結果で書き換える。
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に枠線をつけたいと思います!