**OC的位移枚舉的區分 **swift
//位移枚舉 typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizingFlexibleWidth = 1 << 1, UIViewAutoresizingFlexibleRightMargin = 1 << 2, UIViewAutoresizingFlexibleTopMargin = 1 << 3, UIViewAutoresizingFlexibleHeight = 1 << 4, UIViewAutoresizingFlexibleBottomMargin = 1 << 5 }; //普通枚舉 typedef NS_ENUM(NSInteger, UIViewAnimationTransition) { UIViewAnimationTransitionNone, UIViewAnimationTransitionFlipFromLeft, UIViewAnimationTransitionFlipFromRight, UIViewAnimationTransitionCurlUp, UIViewAnimationTransitionCurlDown, };
Swift 的位移枚舉的區分數組
對於位掩碼,Swift 給出的方案是:選項集合(option sets)。在 C 和 Objective-C 中,一般的作法是將一個布爾值選項集合表示爲一系列值爲 2 的整數次冪的枚舉成員。以後就可使用位掩碼來選擇想要的選項了。舉例來講,NSString 定義了一個名爲 NSStringCompareOptions 的枚舉以表示字符串比較選項:url
typedef enum { NSCaseInsensitiveSearch = 1, NSLiteralSearch = 2, NSBackwardsSearch = 4, NSAnchoredSearch = 8, NSNumericSearch = 64, NSDiacriticInsensitiveSearch = 128, NSWidthInsensitiveSearch = 256, NSForcedOrderingSearch = 512, NSRegularExpressionSearch = 1024 } NSStringCompareOptions;
要同時使用 case-insensitive,backward search,你可使用按位或來組合對應的選項:翻譯
NSStringCompareOptions options = NSCaseInsensitiveSearch | NSBackwardsSearch; // → 5 (= 1 + 4)
譯者注:選擇了第一個選項,能夠用二進制表示爲 001,也就是十進制的 1;選擇了第三個選項,能夠用二進制表示爲 100,也就是十進制的 4;同時選擇第一個和第三個選擇,即 101,等於 001 | 100,同時也是十進制的 5。code
使用選項集合繼承
Swift 使用結構體(struct)來聽從 OptionSet 協議,以引入選項集合,而非枚舉(enum)。爲何這樣處理呢?當枚舉成員互斥的時候,好比說,一次只有一個選項能夠被選擇的狀況下,枚舉是很是好的。可是和 C 不一樣,在 Swift 中,你沒法把多個枚舉成員組合成一個值,而 C 中的枚舉對編譯器來講就是整型,能夠接受任意整數值。 和 C 中同樣,Swift 中的選項集合結構體使用了高效的位域來表示,可是這個結構體自己表現爲一個集合,它的成員則爲被選擇的選項。這容許你使用標準的集合運算#Basic_operations)來維護位域,好比使用 contains 來檢驗集合中是否有某個成員,或者是用 union 來組合兩個位域。另外,因爲 OptionSet 繼承於 ExpressibleByArrayLiteral,你可使用數組字面量來生成一個選項集合。ip
let options: NSString.CompareOptions = [.caseInsensitive, .backwards] options.contains(.backwards) // → true options.contains(.regularExpression) // → false options.union([.diacriticInsensitive]).rawValue :// → 133 (= 1 + 4 + 128)
聽從 OptionSetci
如何建立你本身的選項集合類型呢?僅有的要求是,一個類型爲整型的原始值(rawValue)和一個初始化構造器。對於結構體來講,Swift 一般都會自動提供一個逐一成員構造器(memberwise initializer),因此你並不須要本身寫一個。rawValue 是位域底層的存儲單元。每一個選項都應該是靜態的常量,並使用適當的值初始化了其位域。字符串
struct Sports: OptionSet { let rawValue: Int static let running = Sports(rawValue: 1) static let cycling = Sports(rawValue: 2) static let swimming = Sports(rawValue: 4) static let fencing = Sports(rawValue: 8) static let shooting = Sports(rawValue: 32) static let horseJumping = Sports(rawValue: 512) }
如今,你能夠建立選項集合了,就像這樣:get
let triathlon: Sports = [.swimming, .cycling, .running] triathlon.contains(.swimming) // → true triathlon.contains(.fencing) // → false
須要注意的是,編譯器並無自動把 2 的整數次冪按照升序賦給你的選項——這些工做應該由你來作,你須要正確地賦值,使得每一個選項表明 rawValue 中的其中一個位。若是你給選項賦予了連續的整數(1,2,3,…),就會致使沒法分辨出 .swimming(值爲 3)和 [.running, .cycling](值爲 1 + 2)。 手動賦值的好處有兩個:a. 更直觀易懂;b. 可以徹底掌控每一個選項的值。這也容許你提供額外的屬性來對經常使用的選項進行組合:
extension Sports { static let modernPentathlon: Sports = [.swimming, .fencing, .horseJumping, .shooting, .running] } let commonEvents = triathlon.intersection(.modernPentathlon) commonEvents.contains(.swimming) // → true commonEvents.contains(.cycling) // → false
**選項集合並非集合類型 **
聽從 OptionSet 並不意味着聽從 Sequence 和 Collection 協議,因此你沒法使用 count 來肯定集合中有幾個元素,也沒法使用 for 循環來遍歷選擇的選項。從根本上說,一個選項集合僅僅是簡單的整數值。
本文由 SwiftGG 翻譯組翻譯,已經得到做者翻譯受權,最新文章請訪問 http://swift.gg。