之前一直不曾注意nil,Nil,NULL,NSNull這幾個的差別,一般都是直接用nil。這次趁着排查一個相關的Crash問題順便總結一下,這裡面的坑還是蠻深的,後面還是需要好好的注意一下。
nil
nil 是 Objective-C 對象的字面空值,對應 id 類型的對象,或者使用 @interface 聲明的 Objective-C 對象。比如:
NSObject *someObj = nil;
if(nil == someObj) {
// do something
}
也許nil最顯著的行為是,它雖然為零,仍然可以有消息發送給它。在其他的語言中,比如C++,這樣做會使你的程式崩潰,但在Objective-C中,在nil上調用方法傳回一個零值。這大大的簡化了表達,因為它避免了在使用nil之前對它的檢查:
Nil
Nil 是 Objective-C 類類型的字面空值,對應 Class 類型對象。一般不常用。比如:
Class someCls = Nil;
Class stringCls = [NSString class];
NULL
NULL 是任意的 C 指針的空值。比如:
int *intPointer = NULL;
float *floatPointer = NULL;
struct Node *node = NULL;
NSNull
NSNull是一個Objective-C對象,代表一個空值的類。實際上它隻有一個單例方法:+[NSNull null];注意,它和nil是有很大差別的,nil表示一個空值,而NSNull則是空值對象。
NSNull經常用于Foundation的集合當中(NSArray,NSDictionary等),因為這些集合是無法存儲nil值的,其實我們經常可以在代碼中看到,他們在初始化的時候會以nil結尾符号。舉例來說,在Dictionary中,[dict objectForKey:key] 傳回nil表示dictionary中沒有目前key值對應的對象,也就是說目前key值就不在dictionary中;如果你想要在dictionary中顯示的增加一個空值,則需要用到[NSNull null],如此 [dict objectForKey:key] 才有可能傳回NSNull空值對象。代碼說明:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@"someKey"];
以上代碼會抛出異常,因為nil不能被插入到dict中。
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"someKey"];
上面這段代碼則是正确的,因為[NSNull null]不為nil。
額外的問題:-[NSNull length]: unrecognized selector sent to JSON objects
解決方案:建立一個NSNull的Category,在Category中實作length方法,代碼講解:
@interface NSNull (JSON)
@end
@implementation NSNull (JSON)
- (NSUInteger)length { return 0; }
- (NSInteger)integerValue { return 0; };
- (float)floatValue { return 0; };
- (NSString *)description { return @"0(NSNull)"; }
- (NSArray *)componentsSeparatedByString:(NSString *)separator { return @[]; }
- (id)objectForKey:(id)key { return nil; }
- (BOOL)boolValue { return NO; }
@end
通過NSNull+JSON.m完美解決,隻需要在用的時候import次Category即可。
引用:
http://stackoverflow.com/questions/5908936/difference-between-nil-nil-and-null-in-objective-c
http://stackoverflow.com/questions/16607960/nsnull-length-unrecognized-selector-sent-to-json-objects