ObjC 里面的幾個空值符號經(jīng)常會差點把我搞死,這些基礎(chǔ)的東西一點要弄清楚才行,以提高碼農(nóng)的基本素質(zhì)。
nil
nil 是 ObjC 對象的字面空值,對應(yīng) id 類型的對象,或者使用 @interface 聲明的 ObjC 對象。
例如:
NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;
if(anotherObject == nil)// do something
定義:
// objc.h
#ifndef nil
# if __has_feature(cxx_nullptr)
#?? define nil nullptr
# else
#?? define nil __DARWIN_NULL
# endif
#endif
// __DARWIN_NULL in _types.h
#define __DARWIN_NULL ((void *)0)
Nil
Nil 是 ObjC 類類型的書面空值,對應(yīng) Class 類型對象。
例如:
Class someClass = Nil;
Class anotherClass = [NSStringclass];
定義聲明和 nil 是差不多的,值相同:
// objc.h
#ifndef Nil
# if __has_feature(cxx_nullptr)
#?? define Nil nullptr
# else
#?? define Nil __DARWIN_NULL
# endif
#endif
NULL
NULL 是任意的 C 指針空值。
例如:
int*pointerToInt = NULL;
char*pointerToChar = NULL;
structTreeNode *rootNode = NULL;
定義:
// in stddef.h
#define NULL ((void*)0)
NSNull
NSNull 是一個代表空值的類,是一個 ObjC 對象。實際上它只有一個單例方法:+[NSNull null],一般用于表示集合中值為空的對象。
例子說明:
// 因為 nil 被用來用為集合結(jié)束的標志,所以 nil 不能存儲在 Foundation 集合里。
NSArray *array = [NSArray arrayWithObjects:@"one", @"two", nil];
// 錯誤的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@"someKey"];
// 正確的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"someKey"];
定義:
/*? NSNull.h
Copyright (c) 1994-2012, Apple Inc. All rights reserved.
*/
#import
@interface NSNull : NSObject
+ (NSNull *)null;
@end
NIL 或 NSNil
ObjC 不存在這兩個符號!
小結(jié)
雖然 nil, Nil, NULL 的值相同,理解它們之間的書面意義才重要,讓代碼更加明確,增加可讀性。
參考資料
Difference between nil,NIL and null – Stack Overflow
var:http://magicalboy.com/null-value-in-objective-c/
---------------------------------------------------------------------------------------------------
理解“不存在”的概念不僅僅是一個哲學的問題,也是一個實際的問題。我們是有形宇宙的居民,而原因在于邏輯宇宙的存在不確定性。作為一個邏輯系統(tǒng)的物理體現(xiàn),電腦面臨一個棘手的問題,就是如何用存在表達不存在.
在Objective-C中,有幾個不同種類的不存在。這樣做的原因要追溯到一個頻繁提及的NSHipster,講解Objective-C如何在C的程序范例以及由Smalltalk啟發(fā)的面向?qū)ο蟮姆独屑芷饦蛄旱摹?/p>
C用0來作為不存在的原始值,而NULL作為指針(這在指針環(huán)境中相當于0)。
Objective-C在C的表達不存在的基礎(chǔ)上增加了nil。nil是一個指向不存在的對象指針。雖然它在語義上與NULL不同,但它們在技術(shù)上是相等的。
在框架層面,F(xiàn)oundation定義了NSNull,即一個類方法+null,它返回一個單獨的NSNull對象。NSNull與nil以及NULL不同,因為它是一個實際的對象,而不是一個零值。
另外,在Foundation/NSObjCRuntime.h中,Nil被定義為指向零的類指針。這個nil的鮮為人知的大寫的表兄并不常常出現(xiàn),但它至少值得注意。
關(guān)于nil的一些事
剛被分配的NSObject的內(nèi)容被設(shè)置為0。也就是說那個對象所有的指向其他對象的指針都從nil開始,所以在init方法中設(shè)置self.(association) = nil之類的表達是沒有必要的。
也許nil最顯著的行為是,它雖然為零,仍然可以有消息發(fā)送給它。
在其他的語言中,比如C++,這樣做會使你的程序崩潰,但在Objective-C中,在nil上調(diào)用方法返回一個零值。這大大的簡化了表達,因為它避免了在使用nil之前對它的檢查:
// 舉個例子,這個表達...
if (name != nil && [name isEqualToString:@"Steve"]) { ... }
// …可以被簡化為:
if ([name isEqualToString:@"steve"]) { ... }
了解nil如何在Objective-C中工作可以讓你將這個便利變成一個功能,而不是潛伏在你的應(yīng)用中的bug。要確保避免當nil值不需要的情況,要么通過檢查或者提前返回來安靜的失敗,或者通過增加一個NSParameterAssert來拋出異常。
NSNull:有作沒有
NSNull在Foundation和其它框架中被廣泛的使用,以解決如NSArray和NSDictionary之類的集合不能有nil值的缺陷。你可以將NSNull理解為有效的將NULL或者nil值封裝boxing,以達到在集合中使用它們的目的:
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionary];
mutableDictionary[@"someKey"] = [NSNull null]; // Sets value of NSNull singleton for `someKey`
NSLog(@"Keys: %@", [mutableDictionary allKeys]); // @[@"someKey"]
總的來說,這里的四個表達沒有的值是每個Objective-C程序員都應(yīng)該知道的:
標志 值 含義
NULL(void *)0C指針的字面零值
nil(id)0Objective-C對象的字面零值
Nil(Class)0Objective-C類的字面零值
NSNull[NSNull null]用來表示零值的單獨的對象