Objective-C用BOOL來(lái)編碼真值,它是signed char的typedef,并且用宏YES和NO來(lái)表示真和假础芍。
布爾值用于條件判斷,比如if和while語(yǔ)句数尿,來(lái)進(jìn)行有條件的邏輯或者重復(fù)運(yùn)行。當(dāng)判斷一個(gè)條件語(yǔ)句惶楼,數(shù)值0為“假”右蹦,而其他任何數(shù)值為“真”。因?yàn)镹ULL和nil被定義為0歼捐,所以對(duì)于折現(xiàn)不存在的數(shù)值的條件語(yǔ)句也被判定為“假”何陆。
在Objective-C中,當(dāng)遇到處理真值的參數(shù)豹储、屬性和實(shí)例變量時(shí)贷盲,使用類(lèi)型BOOL。當(dāng)分配字面值時(shí)剥扣,使用宏YES和NO巩剖。
錯(cuò)誤問(wèn)題的錯(cuò)誤答案
新手經(jīng)常在條件判斷時(shí)加入等號(hào)運(yùn)算符:
if ([a isEqual:b] == YES) {
...
}
這不僅僅是不必要的,而且根據(jù)左邊的值钠怯,它有可能會(huì)導(dǎo)致不可預(yù)料的結(jié)果佳魔。正如Big Nerd Ranch blog post, "BOOL's Sharp Edges"中所描述的那樣:
static BOOL different (int a, int b) {
return a - b;
}
然而,因?yàn)锽OOL在實(shí)際中被typedef為signed char晦炊,所以結(jié)果并不會(huì)像預(yù)期的那樣:
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");
}
此結(jié)果為:
11 != 10 10 == 11 512 == 256
它可能符合語(yǔ)法鞠鲜,但是它在語(yǔ)意上完全說(shuō)不通宁脊。所以,取而代之的方法是贤姆,使用==輸出結(jié)果榆苞,或者將數(shù)值通過(guò)!(或者!!)轉(zhuǎn)換成布爾值。
關(guān)于NSNumber和BOOL的真相
下面的表達(dá)式會(huì)輸出什么霞捡?
NSLog(@"%@", [@(YES) class]);
答案是:
__NSCFBoolean
NSCFBoolean是NSNumber類(lèi)簇中的一個(gè)私有的類(lèi)坐漏。它是通往CFBooleanRef類(lèi)型的橋梁,它被用來(lái)給Core Foundation的屬性列表和集合封裝布爾數(shù)值弄砍。CFBoolean定義了常量kCFBooleanTrue和kCFBooleanFalse仙畦。因?yàn)镃FNumberRef和CFBooleanRef在Core Foundation中屬于不同種類(lèi),這樣是有道理的音婶,它們?cè)贜SNumber被以不同的銜接類(lèi)呈現(xiàn)慨畸。
下面的表格是Objective-C中的所有真值類(lèi)型和數(shù)值:
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 |