在代碼中使用Autolayout時,你們都會使用NSDictionaryOfVariableBindings
這個宏,這個宏能夠生成一個變量名到變量值映射的Dictionary。好比NSDictionaryOfVariableBindings(button1, button2)
將會生成一個{ @"button1" = button1, @"button2 = button2 }
的Dictionary。它是怎麼作到的呢?咱們來看看這個宏的定義:xcode
#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)
這個宏定義中有3個參數,後兩個參數不難理解,但第一個參數中間有個#
符號,語法上看起來比較怪異,這個是什麼呢?之前在作越獄的mobilesubstrate開發時,其中定義的一堆宏頻繁使用了這個符號,下面就來揭開#
這個符號在宏定義中的迷霧。函數
咱們的代碼在build時並非直接進行編譯的,在編譯以前還進行了預編譯處理。預編譯會把include或import的文件導入到文件中,同時會將代碼中用到的宏進行替換。注意宏是直接在代碼中替換成宏的定義的,若是有嵌套也會逐層替換。ui
預編譯命令通常都是以#
開頭的,好比#include
、#import
、#if
等,在這裏就不一一說明了,本文主要說明一下#
在宏定義裏面的一些做用。code
在一個參數前加一個#
,預處理時將會變成這個參數名的字符串常量,即字符串化(stringify)。好比:orm
#define GET_NAME(X) #X int a = 0; NSLog(@"%s",GET_NAME(a)); //output: "a" NSLog(@"%s",GET_NAME(a+3)); //output: "a+3"
將會獲得如下輸出:blog
a a+3
能夠看出#
,將參數原樣轉換成字符串常量,若是參數是一個表達式,那麼輸出這個表達式的原樣字符串常量。開發
回頭再看看NSDictionaryOfVariableBindings
的定義:字符串
#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)
若是這樣生成兩個button的映射:get
NSDictionaryOfVariableBindings(button1, button2);
那麼預編譯時就會轉換成:string
_NSDictionaryOfVariableBindings(@"""button1, button2", button1, button2, nil);
因爲兩個常量字符串放在一塊兒就是字符串常量串聯,將變成兩個字符串常量組合在一塊兒的字符串常量,也就是上面是一個空字符串""
和"button1, button2"
串聯,因此上面的代碼等價於:
_NSDictionaryOfVariableBindings(@"button1, button2", button1, button2, nil);
那麼_NSDictionaryOfVariableBindings
函數就能夠將它的第一個參數按逗號,
分割開做爲key,後面就是各個key對應的值了。所以這段代碼就建立了一個內容爲{ @"button1" = button1, @"button2 = button2 }
的Dictionary。
#
在宏定義中的另外一個做用就是用於命名的串聯,用##
就能夠串聯它左右兩邊的命名,好比如下代碼:
#define CONCAT(X, Y) X ## Y NSString *helloworld = @"Hello, world!"; NSLog(@"%@",CONCAT(hello, world)); //output: "Hello, world"
CONCAT(hello, world)
實際被轉換成helloworld
。注意一下,由於宏是預編譯階段進行展開的,就是說在編譯以前,所以代碼中的hello
和world
即便沒有定義其實也是沒問題的,預編譯處理後,這兩個命名是不存在的。
##
在宏定義中能夠放在__VA_ARGS__
以前表示可變參數能夠爲空,不然的話可變參數至少爲一個了。
#define MYLOG(format, ...) NSLog(format, ##__VA_ARGS__) MYLOG(@"Don't make an error!");
上面代碼中MLOG中只有一個參數,若是不加##
,則MLOG至少須要兩個參數,在Xcode裏將會出現編譯錯誤。
轉自:http://blog.xcodev.com/blog/2013/12/16/mists-of-the-sharp/