《iOS三问》--#define用法大全

OC的 #define 命令与在C语言中的非常相似,是一个预处理命令,其作用是在编译之前对你的代码进行预处理,使用在define中定义的字符串value来替换你要替换的字符串key, 其形式如:

#define使用格式
1
#define KEY value

这里要注意几点:

  1. #define 预处理命令顾名思义,是在编译前工作的,所以其优先高于各种编译期间指令,而且享受不到编译器强大的错误提示(所以使用它要格外小心);
  2. 像上面#define使用格式,要注意你的key与value都不要有空格(除非是字符串用引号括住了);
  3. KEY一般使用全大写加下划线组合,至少首字母要大写,这样别人在代码人能一眼看出这是个宏。

1 基本使用

我们一般会这样使用,比如在一个头文件中声明

1
#define PI 3.141592654

到后面要使用圆周率时,就不需要每次都使用3.141592654这个魔术数字,直接使用PI就行,如perimeter = 2 * PI * raiuds;

1.1 括号问题

使用define时,我们建议value一般要加上括号,以避免因替换环境引起的错误,如

因替换环境引起的错误
1
2
3
#define padding 20+10
viewWidth = padding * 2;

上面的语句发生错误,本来我们希望的是: viewWidth = (20 + 10) * 2 = 60;
结果被展开成:viewWidth = 20 + 10 * 2 = 40;

所以,使用define时,value处最好都加上括号:

1
#define padding (20 + 10)

2 条件define

define还可以用于在编译之前做一个条件判断,在编译前,预处理会进行判断,把不符合条件的代码段屏蔽掉。比如我们常用的

1
2
3
4
5
#ifdef DEBUG
#define MGLog(...) NSLog(__VA_ARGS__)
#else
#define MGLog(...)
#endif

这里就作了一个条件判断,如果在之前使用#define DEBUG定义过DEBUG这个宏,就保留if块中的代码;否则,保留else块中的代码。

3 高级使用

3.1 define函数 - 宏方法

#define 声明中还可以使用参数,并且可使用多个参数;这一特性被称为“宏方法”:

1
2
3
#define SQUARE(x) ( (x) * (x) )
此时, y = SQUARE(v + 1); 等价于 y = ( (v + 1) * (v + 1) );。

特别注意 括号问题 ,上面的别写成 #define SQUARE(x) ( x * x ),原因自己想。

3.2 多个参数的宏方法

如果参数中有多个参数,可以在key中使用 ...来传入多个参数,在value中使用##__VA_ARGS__来引用传入的参数。如下面的一个便利新建数组的宏方法:

1
2
#define Array(FIRST, ...) [NSArray arrayWithObjects: FIRST, ##__VA_ARGS__, nil]
其中 ##__VA_ARGS__ 用于表示省略号所代表的所有内容。

3.3 #算符以及##算符

#算符可产生一个 C-语言 格式的字符串(这个在OC中用得比较少)。如:

1
2
#define string(x) #x
// 则 string(testing) == "testing"

#算符用来连接两段字符串。假设你有一组变量,x1 到 x100。如果你想打印其中某一个变量的值。你可以这样定义:

##算符可以直接生成复合的变量名!如:

1
2
3
#define printxvar(n) printf("%i\n", x##n)
// 由此, printxvar(20); 在编译时将被识别为 printf(“%i\n”, x20);。这样只需要输入 printxvar(n);便可以打印出 xn 的值。

其实,##最常用的用途还是上面介绍的 ##VA_ARGS,它可用来抓取省略号所代表的所有内容。

3.4 使用 \ 切分多行宏定义

比如我们常用的weakify与strongify字义

1
2
3
4
5
6
7
#define weakify(var) __weak typeof(var) AHKWeak_##var = var;
#define strongify(var) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
__strong typeof(var) var = AHKWeak_##var; \
_Pragma("clang diagnostic pop")

4 编程中常用的宏

4.1 表示在模块器中

1
2
#if TARGET_IPHONE_SIMULATOR
#endif

4.2 根据target条件编译

可以在项目的 Build Settings中的 Preprocessor Macros中设置target的预编译宏。然后就可以使用下面的代码来根据不同的target跑不同的代码了(一般用于配置)。

1
2
#if defined(BETA)
#endif

5 引用

  1. Kindazrael -《Objective-C #define 用法解析》
坚持原创技术分享,您的支持将鼓励我继续创作!