| 標(biāo)識 | 值 | 含義 |
|---|---|---|
| Null | (void*)0 | C指針的字面零值 |
| nil | (id)0 | ObjC對象的字面零值 |
| Nil | (Class)0 | ObjC類的字面零值 |
| NSNull | [NSNull null] | 用來表示零值的單獨(dú)對象 |
NOTICE: 蘋果的編譯器在編譯時(shí)會(huì)生成objc_msgSend這樣的方法來發(fā)送消息,當(dāng)對象設(shè)置為nil時(shí),它就不會(huì)去尋找是哪個(gè)類實(shí)例的消息,因此什么也不干,這是蘋果的處理方式。
若obj為nil:[obj message]將返回NO,而不是NSException
若obj為NSNull:[obj message]將拋出異常NSException
nil、Nil、NULL的使用對比
先看下面做的一個(gè)實(shí)驗(yàn):
NSArray * array = [NSArray arrayWithObjects:@"good", @"morning", nil];
// array = nil; // 輸出:0
// array = NULL; // 輸出:0
// array = Nil; // 輸出:0
NSLog(@"%ld", array.count);// 分別使用上面三句注釋的語句,輸出值無區(qū)別
Class class = [NSURL class];
// class = Nil; // 輸出:(null)
// class = nil; // 輸出:(null)
// class = NULL; // 輸出:(null)
NSLog(@"%@", class); // 分別使用上面三句注釋的語句,輸出值無區(qū)別
int a = 10; int * p = &a;
// p = NULL; // 輸出:0x0
// p = nil; // 輸出:0x0//
p = Nil; // 輸出:0x0
NSLog(@"%p", p); // 分別使用上面三句注釋的語句,輸出值無區(qū)別
結(jié)論:
- nil、Nil、NULL在使用上是沒有什么區(qū)別的,但是程序員的一個(gè)約定:C結(jié)構(gòu)的指針使用NULL;對象指針使用nil;類對象指針使用Nil。
- 另外NSNull和nil、Nil、NULL具有本質(zhì)上的區(qū)別。NSNull是一個(gè)對象,而nil、Nil、NULL只是給指針賦空值。
- 在另外,給一個(gè)賦值為nil的對象發(fā)送消息,不會(huì)產(chǎn)生異常。當(dāng)然給一個(gè)賦值為Nil、NULL的對象發(fā)送消息也不會(huì)產(chǎn)生異常,這個(gè)在例子中已經(jīng)證實(shí)。故根據(jù)此條結(jié)論的總結(jié)為:nil、Nil、NULL目的都是給一個(gè)指針賦值為空,給空指針發(fā)送消息不會(huì)產(chǎn)生異常
NSNull 到底是個(gè)什么東西?我從來沒有調(diào)用過這個(gè)類,那么它又是哪產(chǎn)生的?
- 通過 search 和排查,我最終定位了這個(gè)問題,這個(gè) NSNull 是由 AFNetworking 的一個(gè)函數(shù)回調(diào)產(chǎn)生的:
- 我在取 responseObject 的某個(gè) value 時(shí),得到了一個(gè) NSNull 對象,而這個(gè)對象本應(yīng)該是一個(gè) NSString 的。
- 通過與 PHP 服務(wù)器同學(xué)聯(lián)調(diào),我們最終發(fā)現(xiàn)了這個(gè)問題產(chǎn)生的原因。
- 原來,服務(wù)器同學(xué)在獲取某個(gè)字段的時(shí)候,不小心填錯(cuò)了參數(shù),導(dǎo)致獲取到的字段為空。他將這個(gè)空作為這個(gè) Key 的 Value 填入了 JSON。
- iOS APP 這邊,AFNetworking 發(fā)現(xiàn)了這個(gè)空,它跟 Objective-C 中的 nil 有著顯著的區(qū)別,因?yàn)?Objective-C 中的 NSDictionary 是不允許某一個(gè) Key 對應(yīng)的 Value 為 nil的。 這個(gè)空,最終被轉(zhuǎn)化成了一個(gè) NSNull 對象。
nil、Nil、NULL、NSNull之間的區(qū)別
nil的含義
指向一個(gè)對象的指針為空,用于給對象指針賦值為空,防止野指針的產(chǎn)生;也稱nil為空對象:表示一個(gè)已經(jīng)被釋放了的對象,和值為空的對象(NSNull)不同。NSNull是一個(gè)對象,只不過這個(gè)對象的值為空
#ifndef nil
# if __has_feature(cxx_nullptr)
# define nil nullptr
# else
# define nil __DARWIN_NULL
# endif
#endif
給對象指針賦值為空:
NSString * name = nil;
NSString * url = nil;
id object = nil;
Nil的含義
指向一個(gè)類的指針為空,用于給類對象指針賦值為空
#ifndef Nil
# if __has_feature(cxx_nullptr)
# define Nil nullptr
# else
# define Nil __DARWIN_NULL
# endif
#endif
給類對象賦值為空:
Class class = Nil;
NULL的含義
指向C類型的指針,用于給C類型的指針賦值為空
#if defined(__need_NULL)
#undef NULL
#ifdef __cplusplus
# if !defined(MINGW32) && !defined(_MSC_VER)
# define NULL __null
# else
# define NULL 0
# endif
#else
# define NULL ((void*)0)
#endif
給C類型指針賦值:
int * a = NULL;
char * ch = NULL;
struct aStruct = NULL;
NSNull的含義
NSNull是一個(gè)類,其繼承自NSObject,只擁有一個(gè)類方法。實(shí)例對象表示這是一個(gè)內(nèi)容為空的對象。主要用于數(shù)組、字典。
NSMutableArray * mArray = [NSMutableArray array];
[mArray addObject:[NSNull null]];
NSLog(@"%@", [mArray firstObject]); // 輸出為:<null>
NSMutableDictionary * dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"null"];
NSLog(@"%@", dict[@"null"]); // 輸出為:<null>
由此可見,可用NSNull的實(shí)例對象在數(shù)組、字典中占位,其所占有的位置為空。