天天看點

iOS 宏 常見運用 define

簡介

宏定義是C語言提供的三種預處理功能的其中一種,這三種預處理包括:宏定義、檔案包含、條件編譯。

宏定義又稱為宏代換、宏替換,簡稱“宏”。

預處理(預編譯)工作也叫做宏展開:将宏名替換為字元串。

掌握”宏”概念的關鍵是“換”。一切以換為前提、做任何事情之前先要換,準确了解之前就要“換”。

即在對相關指令或語句的含義和功能作具體分析之前就要換:

例如:

#define Pi 3.1415926

把程式中出現的Pi全部換成3.1415926

其它的宏也是同理

注:宏是沒有類型檢測的 在使用的時候要注意宏的類型 比如說一個 數字的宏 你不能拿來當成NSString來使用

不帶參數的宏

不帶參數的宏,其實就是做一下簡單替換

比如說:

// 是否模拟器

#define isSimulator NSNotFound != [[[UIDevice currentDevice] model] rangeOfString:@”Simulator”].location

在代碼中出現 isSimulator的地方都會替換成

NSNotFound != [[[UIDevice currentDevice] model] rangeOfString:@”Simulator”].location

這段代碼 其實他的值是一個BOOL類型的

還有

#define PI 3.1415926 

出現PI的地方那個都會會變成3.1415926

這個沒什麼要多餘的,直接過了哒 =)

帶參數的宏

宏除了一般的字元串替換,還要做參數代換,這個是Macro Magic裡面最具有魔法的點

簡單參數宏

#define ADD(a,b) a+b

在代碼中出現

int total = ADD(2,3);

編譯的時候就會替換成:int total = 2+3;

這裡面有個坑,要跳過去

比如定義一個宏:#define S(r) r*r

代碼中使用:S(a+b) 這個時候就會替換成 a+b*a+b 發現問題了吧

是以正确的宏應該是這樣的:#define S(r) (r)*(r)

這個注意表達式的優先級别就可以繞過這個坑了。

宏定義Class

這個用法個人感覺比較少見,但是确實很實用,比如定義一個準從相同協定

下面上一個例子看看

#define CreateClass(className)\ @interface className : NSObject\ -(void)sayHello;\ @end\ @implementation className\ -(void)sayHello \ {\ NSLog(@"Hello,%d",__LINE__);\ }\ @end\

CreateClass(ABC)

這樣就定義了一個ABC的類 有木有很神奇?

Block變量弱引用宏

在使用Block的時候 為了防止循環引用 需要變量弱引用 代碼會比較麻煩

有了宏一切變得簡單了 比如:

#define WEAK_REF(obj) \

__weak typeof(obj) weak_##obj = obj; \

注:\ 在宏中是換行的意思,少了它換行會報錯; ##是連接配接符号,将weak與obj這個參數連接配接成一個字元串

使用時:

WEAK_REF(abc);

Block中用:weak_abc即可

__LINE__宏

在Foundation中定義了一個宏叫 __LINE__ 這個宏是告訴你代碼在第幾行

你可以在任何一行代碼列印__LINE__(NSLog(@”%d”,__LINE__))看看 是不是NSLog所在代碼的行數?

這個大家可以想,如果做背景異常判斷的時候把這個代碼行數打出來,那不是很容易定位到問題所在地方?

類似__LINE__這個宏還有 __FILE__   __FUNCTION__

帶參數的例子也講的差不多了,其他的大家發動思維去做吧 =)

條件編譯

條件編譯,也是一個魔法

最常用的就是各種環境 編譯出不同的代碼,不如一個URL 請求的測試環境和正式環境在開發和線上不是同一個,那一個宏 的條件編譯就解決這個問題了

例子:

#ifdef ABC

URL = @”www”;

#else

URL = @”wwww”

#endif

在來一個例子:

NSLog問題,一般線上上上不需要列印出來,那通過宏也是可以控制的

在xxx.pch檔案中加入

#ifdef __OPTIMIZE__

# define NSLog(…) {}

#else

# define NSLog(…) NSLog(__VA_ARGS__)

#endif

出一個release版本的時候NSLog這個宏就沒有任何作用

解釋:

  • __OPTIMIZE__ 這個宏在release編譯的時候Xcode會定義
  • 把NSLog作為一個宏定義
  • __VA_ARGS__ 這個是一個可變參數宏

預處理指令簡介

  • #define 定義一個預處理宏
  • #undef 取消宏的定義
  • #include 包含檔案指令
  • #include_next 與#include相似, 但它有着特殊的用途
  • #if 編譯預進行中的條件指令, 相當于C文法中的if語句
  • #ifdef 判斷某個宏是否被定義, 若已定義, 執行随後的語句
  • #ifndef 與#ifdef相反, 判斷某個宏是否未被定義
  • #elif 若#if, #ifdef, #ifndef或前面的#elif條件不滿足, 則執行#elif之後的語句, 相當于C文法中的else-if
  • #else 與#if, #ifdef, #ifndef對應, 若這些條件不滿足, 則執行#else之後的語句, 相當于C文法中的else
  • #endif #if, #ifdef, #ifndef這些條件指令的結束标志.
  • defined 與#if, #elif配合使用, 判斷某個宏是否被定義
  • #line 标志該語句所在的行号
  • # 将宏參數替代為以參數值為内容的字元竄常量
  • ## 将兩個相鄰的标記(token)連接配接為一個單獨的标記
  • #pragma 說明編譯器資訊
  • #warning 顯示編譯警告資訊
  • #error 顯示編譯錯誤資訊

好了,講的比較亂,大家能用多少是多少吧