Swift 位移枚舉的按位或運算

**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。

相關文章
相關標籤/搜索