在代码中使用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/