1. 程式人生 > >Objective-C 列舉 中位運算 的使用

Objective-C 列舉 中位運算 的使用

前言

Enum,也就是列舉,從C語言開始就有了,C++、Java、Objective-C、Swift這些語言,當然都有對應的列舉型別,功能可能有多有少,但是最核心的還是一個—-規範的定義程式碼中的狀態、選項等“常量”。

 Use Enumerations for States, Options, and Status Codes

本節的內容就是如何正確的使用列舉。

狀態與選項的區別(states and options)

在用 enum 之前,我個人覺得,區分一下狀態和選項的概念還是很必要的。

狀態,同時只能有一種,如“ OK ”,“ Error ”,不可能同時是OK和Error。

選項,同時可以有一種或一種以上,如App可以 同時 支援橫屏和豎屏,橫屏豎屏在這個時候就是“螢幕方向”的兩種不同的選項。

接下來,我們看看如何用列舉定義狀態和選項。

enum與狀態(states)

不好的做法

經常看到這樣的寫法:

#define STATE_OK 0
#define STATE_ERROR 1
#define STATE_UNKNOW 2

//直接用int型變數接收
int STATE = STATE_UNKNOW;

這樣做有如下“不恰當”:

  • 巨集定義沒有型別約束,只是單純的替換。
  • 無法限制狀態的所有情況,如,認為的將STATE賦值成3,程式可能就會出錯,找不到匹配的狀態,因為編譯器不會對“ STATE = 3;
     ”提出警告。

正確的做法

typedef enum _TTGState{
	TTGStateOK  = 0,
	TTGStateError,
	TTGStateUnknow
} TTGState;
//指明列舉型別
TTGState state = TTGStateOK;

用的時候就如下:

- (void)dealWithState:(TTGState)state {
	switch (state) {
		case TTGStateOK:
			//...
			break;
		case TTGStateError:
			//...
			break;
		case TTGStateUnknow:
//... break; } }

enum與選項 (options)

選項,就是說一個“選項變數”的型別要能夠同時表示一個或多個組合的選擇,如下例子:

//方向,可同時支援一個或多個方向
typedef enum _TTGDirection {
    TTGDirectionNone = 0,
    TTGDirectionTop = 1 << 0,
    TTGDirectionLeft = 1 << 1,
    TTGDirectionRight = 1 << 2,
    TTGDirectionBottom = 1 << 3
} TTGDirection;

看,這裡的選項是用 位運算 的方式定義的,這樣的好處就是,我們的選項變數可以如下表示:

//用“或”運算同時賦值多個選項
TTGDirection direction = TTGDirectionTop | TTGDirectionLeft | TTGDirectionBottom;
//用“與”運算取出對應位
if (direction & TTGDirectionTop) {
	NSLog(@"top");
}
if (direction & TTGDirectionLeft) {
	NSLog(@"left");
}
if (direction & TTGDirectionRight) {
	NSLog(@"right");
}
if (direction & TTGDirectionBottom) {
	NSLog(@"bottom");
}

direction變數的實際記憶體如下:

這樣,用位運算,就可以同時支援多個值。

enum在Objective-C中的“升級版”

一般來說,我們不能指定列舉變數的實際型別是什麼,就是說,我們不知道列舉最後是int型,還是其他的什麼型別。但是從C++ 11開始,我們可以為列舉指定其實際的儲存型別,如下語法:

enum TTGState : NSInteger {/*...*/};

但是,我們在定義列舉的時候如何保證相容性呢?Foundation框架已經為我們提供了更加“統一、便捷”的列舉定義方法,我們重新定義上面的例子:

//NS_ENUM,定義狀態等普通列舉
typedef NS_ENUM(NSUInteger, TTGState) {
	TTGStateOK = 0,
	TTGStateError,
	TTGStateUnknow
};
//NS_OPTIONS,定義選項
typedef NS_OPTIONS(NSUInteger, TTGDirection) {
	TTGDirectionNone = 0,
	TTGDirectionTop = 1 << 0,
	TTGDirectionLeft = 1 << 1,
	TTGDirectionRight = 1 << 2,
	TTGDirectionBottom = 1 << 3
};

所以,在開發Mac、iOS程式中,最好所有的列舉都用“ NS_ENUM ”和“ NS_OPTIONS ”定義,保證統一。

總結

充分的用好列舉,可以增強程式碼的可讀性,減少各種“錯誤”,讓程式碼更加的規範。