iOS 枚舉講解

来源:http://www.cnblogs.com/lurenq/archive/2017/10/19/7693764.html
-Advertisement-
Play Games

枚舉增強程式的可讀性,用法上還是需要註意的 1.C語言的寫法 enum XMPPReconnectFlags { kShouldReconnect = 1 << 0, // If set, disconnection was accidental, and autoReconnect may be ...


枚舉增強程式的可讀性,用法上還是需要註意的

1.C語言的寫法

enum XMPPReconnectFlags
{
 kShouldReconnect   = 1 << 0,  // If set, disconnection was accidental, and autoReconnect may be used
 kMultipleChanges   = 1 << 1,  // If set, there have been reachability changes during a connection attempt
 kManuallyStarted   = 1 << 2,  // If set, we were started manually via manualStart method
 kQueryingDelegates = 1 << 3,  // If set, we are awaiting response(s) from the delegate(s)
};

或者是

typedef enum XMPPReconnectFlags
{
 kShouldReconnect   = 1 << 0,  // If set, disconnection was accidental, and autoReconnect may be used
 kMultipleChanges   = 1 << 1,  // If set, there have been reachability changes during a connection attempt
 kManuallyStarted   = 1 << 2,  // If set, we were started manually via manualStart method
 kQueryingDelegates = 1 << 3,  // If set, we are awaiting response(s) from the delegate(s)
}XMPPReconnectFlags;//此處的XMPPReconnectFlags為別名

2.OC的寫法

typedef NS_ENUM(NSInteger, XMPPMessageBodyType) {
    XMPPMessageBodyTypeText = 1,       //文本
    XMPPMessageBodyTypeImage,          //圖片
    XMPPMessageBodyTypeSound,          //語音
    XMPPMessageBodyTypeMap,            //地理信息(文本)
    XMPPMessageBodyTypeNotification,   //通知
    XMPPMessageBodyTypeCustom,         //自定義
    XMPPMessageBodyTypeVideo,          //視頻
    XMPPMessageBodyTypeExpression,     //表情
};

第一個枚舉值只要NSInteger類型,後面的依次累加,中間再重新賦值,後面的會從賦值處重新累加

3.NS_ENUM和NS_OPTIONS

NS_ENUM和NS_OPTIONS本質是一樣的,僅僅從字面上來區分其用途。NS_ENUM是通用情況,NS_OPTIONS一般用來定義具有位移操作或特點的情況

typedef NS_OPTIONS(NSInteger, ShareViewItemType) {
    ShareViewItemTypeWX = 1,
    ShareViewItemTypeWXFC = 1 << 0,
    ShareViewItemTypeQQ= 1 << 1,
    ShareViewItemTypeWB= 1 << 1,
    ShareViewItemTypeReport= 1 << 3,
    ShareViewItemTypeBarrage = 1 << 4,
    ShareViewItemTypeAll = 1 << 5,
};

如果多選枚舉,那麼需要這樣判斷

+ (instancetype)shareViewWithDic:(NSDictionary*)dic shareViewItemType:(ShareViewItemType)shareViewItemType;
{
    if (shareViewItemType == (ShareViewItemTypeWX|ShareViewItemTypeWXFC)) {
        // code
    }
}

4.官方的全選枚舉

UIControl的枚舉

typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
    UIControlEventTouchDown                                         = 1 <<  0,      // on all touch downs
    UIControlEventTouchDownRepeat                                   = 1 <<  1,      // on multiple touchdowns (tap count > 1)
    UIControlEventTouchDragInside                                   = 1 <<  2,
    UIControlEventTouchDragOutside                                  = 1 <<  3,
    UIControlEventTouchDragEnter                                    = 1 <<  4,
    UIControlEventTouchDragExit                                     = 1 <<  5,
    UIControlEventTouchUpInside                                     = 1 <<  6,
    UIControlEventTouchUpOutside                                    = 1 <<  7,
    UIControlEventTouchCancel                                       = 1 <<  8,

    UIControlEventValueChanged                                      = 1 << 12,     // sliders, etc.
    UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 13,     // semantic action: for buttons, etc.

    UIControlEventEditingDidBegin                                   = 1 << 16,     // UITextField
    UIControlEventEditingChanged                                    = 1 << 17,
    UIControlEventEditingDidEnd                                     = 1 << 18,
    UIControlEventEditingDidEndOnExit                               = 1 << 19,     // 'return key' ending editing

    UIControlEventAllTouchEvents                                    = 0x00000FFF,  // for touch events
    UIControlEventAllEditingEvents                                  = 0x000F0000,  // for UITextField
    UIControlEventApplicationReserved                               = 0x0F000000,  // range available for application use
    UIControlEventSystemReserved                                    = 0xF0000000,  // range reserved for internal framework use
    UIControlEventAllEvents                                         = 0xFFFFFFFF
};

最後一個 UIControlEventAllEvents賦值為0xFFFFFFFF,意為全選,實際工程使用沒有問題,很方便,但是在
Archive的時候會報錯


屏幕快照 2016-06-29 下午12.28.10.png


這個地方需要這樣改

typedef NS_OPTIONS(NSUInteger, ShareViewItemType) {
    ShareViewItemTypeWX = 1,
    ShareViewItemTypeWXFC = 1 << 0,
    ShareViewItemTypeQQ= 1 << 1,
    ShareViewItemTypeWB= 1 << 1,
    ShareViewItemTypeReport= 1 << 3,
    ShareViewItemTypeBarrage = 1 << 4,
    ShareViewItemTypeAll = 0xFFFFFFFF,
};

你可以這樣判斷條件

+ (instancetype)shareViewWithDic:(NSDictionary*)dic shareViewItemType:(ShareViewItemType)shareViewItemType;
{
// 入參shareViewItemType為ShareViewItemTypeAll
    if (shareViewItemType & ShareViewItemTypeBarrage) {
        // code
    }
}

5.使用層面的理解

在這裡首先講如何簡單的使用, 僅僅是使用層面(有理解錯誤的地方幫忙糾正), 然後我們在去理解位運算符! 在下麵的圖中我們可以看見枚舉值中有<<(位運算符:左移):


 

如果我們在枚舉值中看見<<那我們就可以通過|(位運算符:或)進行組合使用如下代碼為例:

 //隨便添加一個UITextField
 UITextField *field = [UITextField new];
 //Begin,Changed,DidEnd都能觸發UITextField的事件
 [field addTarget:self action:@selector(textFieldDidChanged) forControlEvents: UIControlEventEditingDidBegin |
                  UIControlEventValueChanged |
                  UIControlEventEditingDidEnd
     ];

 [self.view addSubview:field];

如下圖枚舉值中沒有<<,這就是普通的NSInteger類型的枚舉, 所以不能組合使用:


 

那蘋果官方是怎麼知道我們多個條件組合使用了呢? 答案是通過&(位運算符:與)進行判斷的:

//controlEvents是組合使用後的一個值
 NSUInteger controlEvents = UIControlEventEditingDidBegin | UIControlEventValueChanged | UIControlEventEditingDidEnd;
    /**
    //通過 & 來判斷是否包含:
    UIControlEventEditingDidBegin,
    UIControlEventValueChanged,
    UIControlEventEditingDidEnd
     */
    if (controlEvents & UIControlEventEditingDidBegin) {

        NSLog(@"UIControlEventEditingDidBegin");

    }else if (controlEvents & UIControlEventValueChanged) {

        NSLog(@"UIControlEventValueChanged");

    }else if (controlEvents & UIControlEventEditingDidEnd) {

        NSLog(@"UIControlEventEditingDidEnd");
    }

那麼我們接下來看看使用過程中牽扯到的位運算符, 我們會在下麵舉個例子!

6.理解位運算符

首先我們有一個枚舉, 下麵代碼2種寫法我們暫時先不用管,等位運算符講完我們會討論枚舉的巨集使用:

//typedef NS_OPTIONS(NSInteger, myTests) {
//    nameA = 1 << 0,
//    nameB = 1 << 1,
//    nameC = 1 << 2,
//    nameD = 1 << 3,
//};

typedef enum {
    nameA = 1 << 0,
    nameB = 1 << 1,
    nameC = 1 << 2,
    nameD = 1 << 3,

}myTests;

/**
 nameA = 1 << 0 :值為1(2的0次方)
 nameB = 1 << 1 :值為2(2的1次方)
 nameC = 1 << 2 :值為4(2的2次方)
 nameD = 1 << 3 :值為8(2的3次方)
 */

通過&進行判斷我們來看看輸出結果如下圖:


 

我們得到NSInteger value = nameA | nameB;的組合的值, 判斷結果是:1nameA的值, 2nameB的值, nameCnameD沒有組合使用所以值為0,最後我們知道如果value & nameC0說明value不包含nameC 相反則包含!

還有一點就是value & nameA就是nameA的值為1, value & nameB就是nameB的值為2

  • <<(左移):a << b就表示把a轉為二進位後左移b位(在後面添b0
  • |(或):只要有一個為1, 結果就是1
  • &(與):只要有二個為1, 結果才是1

我們已經知道nameA = 1, nameB = 2, nameC = 4, nameD = 8下麵來通過二進位來解釋:

 NSInteger value = nameA | nameB | nameC | nameD;
     轉成二進位:
     nameA: 0 0 0 1
       |
     nameB: 0 0 1 0
       |
     nameC: 0 1 0 0
       |
     nameD: 1 0 0 0
    ----------------
     value: 1 1 1 1
     上面是使用 | 得出value的值為1111(|的意思是有一個為1結果就為1)


     下麵是使用 & 判斷輸出的值(&的意思就是有二個為1結果才為1)

      value: 1 1 1 1         value: 1 1 1 1
        &                      &
      nameA: 0 0 0 1         nameB: 0 0 1 0
     ----------------       ----------------
      結果值: 0 0 0 1         結果值: 0 0 1 0

      我就寫2個例子:0001就是nameA的值, 0010就是nameB的值

相信大家已經明白其中的道理了, 接下來我們來看看枚舉的巨集, 為了更好閱讀也可以看下麵的截圖:


 

7.枚舉的巨集(NS_ENUMNS_OPTIONS)

NS_ENUMNS_OPTIONS巨集提供了一個簡潔、定義枚舉和C語言選項的簡單方法。

The NS_ENUM and NS_OPTIONS macros provide a concise, simple way of defining enumerations and options in C-based languages. These macros improve code completion in Xcode and explicitly specify the type and size of your enumerations and options. Additionally, this syntax declares enums in a way that is evaluated correctly by older compilers, and by newer ones that can interpret the underlying type information.

這是最初的使用方法:

enum {
        UITableViewCellStyleDefault,
        UITableViewCellStyleValue1,
        UITableViewCellStyleValue2,
        UITableViewCellStyleSubtitle
};
typedef NSInteger UITableViewCellStyle;

--------------------------------------------------

enum {
        UIViewAutoresizingNone                 = 0,
        UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
        UIViewAutoresizingFlexibleWidth        = 1 << 1,
        UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
        UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
        UIViewAutoresizingFlexibleHeight       = 1 << 4,
        UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
typedef NSUInteger UIViewAutoresizing;

通過使用枚舉的巨集:

NS_ENUM:是用來聲明一般的NSInteger(下麵代碼使用NSInteger)類型的枚舉

Use the NS_ENUM macro to define enumerations, a set of values that are mutually exclusive.

NS_OPTIONS:是用來聲明位掩碼(bitmasked)

Use the NS_OPTIONS macro to define options, a set of bitmasked values that may be combined together.

//NS_ENUM
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
        UITableViewCellStyleDefault,
        UITableViewCellStyleValue1,
        UITableViewCellStyleValue2,
        UITableViewCellStyleSubtitle
};

--------------------------------------------------

//NS_OPTIONS
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
};

NS_OPTIONSNS_ENUMenum 是有什麼區別呢?

1.通過上面介紹我們可以看出enum可以聲明一般類型和位掩碼(bitmasked)類型

2.NS_ENUM聲明一般類型, NS_OPTIONS聲明掩碼(bitmasked)類型

3.那麼問題又來了, 直接用enum不就可以了? 答案不是這樣的, 蘋果建議我們在OC中使用NS_ENUMNS_OPTIONS, 為什麼呢? 因為他們除了推斷出不同類型的枚舉,再就是當編譯Objective-C++模式,它們產生的代碼是不同的, 就是因為不同所以混編的時候使用enum會報錯!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 非同步實時搜索jquery select插件 一、先看看效果。 二、做此插件的原因。 1.數據量過大(幾千、幾萬條),無法一次性全部載入。 2.現有插件各不相同,無法滿足功能需求。 3.美觀性,可控性不足。 三、如何使用。 1.html和js 2.實例。 3.詳細配置。 還有一些其它的api,詳細請看 ...
  • 品牌:超凡魔術師h5案例地址:http://www.199case.com/caseview.aspx?id=2668 1、內容:一個以”超凡魔術師“為主題的視頻+回答類的推文,用戶可以通過觀看一段一個人物在表演魔術的視頻,在其間用戶可以選擇兩個選項中的一項與之進行互動。 2、亮點:這篇推文最大的亮 ...
  • 1、java堆得Young區由哪些組成: Java堆由Perm區和Heap區組成,Heap區由Old區和New區(也叫Young區)組成,New區由Eden區、From區和To區(Survivor)組成。 2、實現ContentProvider需要實現哪些方法: insert、delete、quer ...
  • #菜單 pod 'LGSideMenuController' # 刷新 pod 'MJRefresh' # 網路請求 pod 'AFNetworking', '~> 3.0' # 圖片緩存 pod 'SDWebImage', '~> 4.0' # 數據解析 pod 'MJExtension' # 網 ...
  • CVPixelBufferRef YUV NV12 pixelFormatType 創建 數據填充 數據讀取 CGImageRef to CVPixelBufferRef ...
  • 2017.10.20 之前參加一個大三學長的創業項目,做一個智能的車鎖App,用到嵌入式等技術,App需要藍牙、實時位置等技術,故查了幾篇相關技術文章,以此參考! //先說說如何開啟藍牙設備和設置可見時間: private void search() { BluetoothAdapter adapt ...
  • 實現目標 先來一張微信功能截圖看看要做什麼 其實就是有一個目的地,點擊目的地的時候彈出可選擇的應用進行導航。 大腦動一下,要實現這個功能應該大體分成兩步: 底部菜單這裡用PopupWindow來做。 實現 1、菜單顯示 PopupWindow支持傳入view進行彈出展示,所有我們直接寫一個菜單佈局, ...
  • 直奔主題 第一步:為AndroidStudio安裝Kotlin插件 線上安裝步驟:File—>Settings—>Plugins—>Install JetBrains plugin…出現以下界面,選中Kotlin 點擊右邊的Install(因為我的已經安裝了所以顯示的是Update升級) 然後就是漫 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...