nil和Nil
nil通常表示類的實(shí)例對(duì)象的空值,Nil通常表示類的對(duì)象的空值,在OC中調(diào)用類的實(shí)例方法,最終也是調(diào)用了類的方法,所以,nil和Nil幾乎是一回事。在官方文檔中只搜到了對(duì)Nil的定義:
Nil
Defines the id of a null class.
下面來看具體的代碼:
NSObject *object = [[NSObject alloc] init];
NSLog(@"%p, %p" , object, &object);
object = nil; // or Nil
NSLog(@"%p, %p" , object, &object);
創(chuàng)建了一個(gè)NSObject類型的實(shí)例對(duì)象,賦值給指針變量object。打印這個(gè)實(shí)例對(duì)象的地址和object指針變量的地址。
0x600000008bd0, 0x7ffee2a4d4c8
然后將object變量賦值為nil(Nil),因?yàn)镹SObject類型的實(shí)例對(duì)象引用計(jì)數(shù)為0,該對(duì)象被釋放,再次打印這個(gè)實(shí)例對(duì)象的地址和object指針變量的地址。
0x0, 0x7ffee2a4d4c8
這個(gè)對(duì)象的地址被置為空(0),而object指針變量的地址依然存在。
所以,將指針變量賦值為nil(Nil),可以理解為將指針指向了一個(gè)系統(tǒng)預(yù)設(shè)的好的空對(duì)象((id)0),也可以理解為空指針。
NULL
NULL是C語(yǔ)言中的語(yǔ)法,表示一個(gè)空指針。因?yàn)镺bjectivc-C是基于C語(yǔ)言的,所以也兼容NULL,在
// C
void *p = NULL;
printf("%p", p);
// Objective-C
NSObject *object = [[NSObject alloc] init];
NSLog(@"%p, %p" , object, &object);
object = NULL; // or Nil, nil
NSLog(@"%p, %p" , object, &object);
打印的結(jié)果也是:
0x0
0x600000003c10, 0x7ffeedb244c8
0x0, 0x7ffeedb244c8
NSNULL
蘋果官方對(duì)NSNULL的定義如下:
NSNULL
A singleton object used to represent null values in collection objects that don’t allow nil values.
翻譯過來就是
NSNULL是一個(gè)單例對(duì)象,用于表示集合對(duì)象中不允許nil值的空值。
NSNULL是只有一個(gè)類方法+ (NSNull *)null,該方法會(huì)返回NSNULL的單例。
NSNull *null = [NSNull null];
NSLog(@"%@, %p", null, &null);
將NSNull類型的指針指向[NSNull null]返回的單例對(duì)象,賦值給變量null,打印這個(gè)單例對(duì)象的信息、單例對(duì)象的地址和指針的地址。
<null>, 0x103a07fc0, 0x7ffeeddd24c8
這個(gè)NSNull對(duì)象有具體的地址,只是存的值為null,并不是一個(gè)空的對(duì)象。
NSNull的用途:
服務(wù)器返回的JSON數(shù)據(jù)中偶爾會(huì)出現(xiàn)空值的情況,在把JSON數(shù)據(jù)轉(zhuǎn)化為NSArray或者NSDictionary后,這些類的對(duì)象中會(huì)存在空值,在使用時(shí)會(huì)引起異常。
判斷數(shù)組中是否有空值。
NSArray *array = @[@"111", [NSNull null], @"333"];
NSLog(@"%@", array);
for (id item in array) {
NSLog(@"%@", [item lowercaseString]);
}
該段代碼期望將數(shù)組中字符串轉(zhuǎn)為小寫并打印,但是在運(yùn)行時(shí)會(huì)引起崩潰,錯(cuò)誤信息如下:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull lowercaseString]: unrecognized selector sent to instance 0x10ebe4fc0'
現(xiàn)將代碼改為:
NSArray *array = @[@"111", [NSNull null], @"333"];
NSLog(@"%@", array);
for (id item in array) {
// 過濾數(shù)組中包含空值的元素
if (item == [NSNull null]) {
continue;
}
NSLog(@"%@", [item lowercaseString]);
}
加上一個(gè)空值的判斷就可以正常運(yùn)行。NSDictionary也是如此。
NSDictionary *dictionary = @{@"key1": @"value1", @"key2": [NSNull null]};
NSLog(@"%@", dictionary);
for (id value in dictionary.allValues) {
// 過濾字典中包含空值的value
if (value == [NSNull null]) {
continue;
}
NSLog(@"%@", [value lowercaseString]);
}
總結(jié)
nil和Nil表示Objective-C中的空對(duì)象,NULL表示C/C++中的空對(duì)象,所以實(shí)際使用中三者沒有區(qū)別??梢詫⑦@些值賦值給指針變量,釋放指針變量指向的對(duì)象。
NSNull是一個(gè)類,這個(gè)類會(huì)返回一個(gè)對(duì)象表示值為空(<null>),可以通過這樣的仿佛對(duì)Collection類型的對(duì)象進(jìn)行空值判斷。