逗号运算符

将类名转为String,同时带有编译检查

1
2
3
4
5
6
7
8
/**
* 如:CLASS_NAME(NSObject) => @"NSObject"
*
* @param class 类
*
* @return 返回类名的字符串
*/
#define CLASS_NAME(class) @(((void)(NO && ((void)[class new], NO)), #class))

逗号运算符

逗号运算符 - 维基百科,自由的百科全书

1
2
3
4
5
6
7
/** 
* 将a的值增加2,然后将a + b的值分配给i。
* 逗号在第一行中充当分隔符,在第二行中充当运算符。
* 结果:a = 3,b = 2,c = 3,i = 5
*/
int a=1, b=2, c=3;
int i = (a += 2, a + b);
1
2
3
4
5
6
7
8
9
10
11
@(((void)(NO && ((void)[class new], NO)), #class))
// [class new] 初始化值,当没有这个类时,编译器会报错
@(((void)(NO && ((void)[class new], NO)), #class)) => ((void)[class new], NO)
// && 运算
@(((void)(NO && NO), #class) => (void)(NO && NO))
// 逗号运算
@(((void)NO, #class))
// 实际算式
@(((void)(NO && ((void)[class new], NO)), #class)) => @(#class)
// 为什么不这么写? - 优化
@((((void)[class new], NO), #class))

void的作用

由于左侧的算式是一个未使用的值,为避免编译器 warning。通过 void 强转一下。

@() 的作用

转 NSString

1
2
3
4
(lldb) e "char"
(const char [5]) $5 = "char"
(lldb) e @("char")
(NSTaggedPointerString *) $6 = 0x8a65d8f551e812f0 @"char"

类似特性

1
#define keypath2(OBJ, PATH) \ (((void)(NO && ((void)OBJ.PATH, NO)), # PATH))

通过 OBJ.PATH 实现自动补全