Objective-C用BOOL来编码真值,它是signed char的typedef,并且用宏YES和NO来表示真和假。
布尔值用于条件判断,比如if和while语句,来进行有条件的逻辑或者重复运行。当判断一个条件语句,数值0为“假”,而其他任何数值为“真”。因为NULL和nil被定义为0,所以对于折现不存在的数值的条件语句也被判定为“假”。
在Objective-C中,当遇到处理真值的参数、属性和实例变量时,使用类型BOOL。当分配字面值时,使用宏YES和NO。
错误问题的错误答案
新手经常在条件判断时加入等号运算符:
if ([a isEqual:b] == YES) {
...
}
这不仅仅是不必要的,而且根据左边的值,它有可能会导致不可预料的结果。正如Big Nerd Ranch blog post, "BOOL's Sharp Edges"中所描述的那样:
static BOOL different (int a, int b) {
return a - b;
}
然而,因为BOOL在实际中被typedef为signed char,所以结果并不会像预期的那样:
if (different(11, 10) == YES) {
printf ("11 != 10\n");
} else {
printf ("11 == 10\n");
}
if (different(10, 11) == YES) {
printf ("10 != 11\n");
} else {
printf ("10 == 11\n");
}
if (different(512, 256) == YES) {
printf ("512 != 256\n");
} else {
printf ("512 == 256\n");
}
此结果为:
11 != 10 10 == 11 512 == 256
它可能符合语法,但是它在语意上完全说不通。所以,取而代之的方法是,使用==输出结果,或者将数值通过!(或者!!)转换成布尔值。
关于NSNumber和BOOL的真相
下面的表达式会输出什么?
NSLog(@"%@", [@(YES) class]);
答案是:
__NSCFBoolean
NSCFBoolean是NSNumber类簇中的一个私有的类。它是通往CFBooleanRef类型的桥梁,它被用来给Core Foundation的属性列表和集合封装布尔数值。CFBoolean定义了常量kCFBooleanTrue和kCFBooleanFalse。因为CFNumberRef和CFBooleanRef在Core Foundation中属于不同种类,这样是有道理的,它们在NSNumber被以不同的衔接类呈现。
下面的表格是Objective-C中的所有真值类型和数值:
Name | Typedef | Header | True Value | False Value |
---|---|---|---|---|
BOOL | signed char | objc.h | YES | NO |
bool | _Bool(int) | stdbool.h | true | false |
Boolean | unsigned char | MacTypes.h | TRUE | FALSE |
NSNumber | __NSCFBoolean | Foundation.h | @(YES) | @(NO) |
CFBooleanRef | struct | CoreFoundation.h | kCFBooleanTrue | kCFBooleanFalse |