原文:http://nshipster.com/nil/
理解“空”的概念既是一个哲学问题也是一个实际问题。我们是某个世界的居民,原因在于一个合乎逻辑的宇宙存在诸多不确定性。作为逻辑系统的物理表示,计算机面临着怎样使用某种东西来表示“空”的问题。
在Objective-C中,有几个不同的表示“空”的变量。这个可以追溯到之前提及的Objective-C如何将C语言的过程范例与Smalltalk式的面向对象范例桥接起来。
C用“0”表示原子数据的“空”,NULL(在指针的上下文中,等同于“0”)表示指针是“空”。
Objective-C在C的基础上增加了nil。nil是一个指向空的对象指针。尽管语义上与NULL不同,但是在技术上他们是等价的。
在框架的级别上,Foundation定义了NSNull。它定义了一个类方法“+null”,用来返回NSNull的单例对象。NSNull不同于nil和NULL,因为它是一个真实的对象而不是零值。
另外,在Foundation/NSObjCRuntime.h头文件中,Nil被定义成指向空的类指针。这个鲜有人知的首字母大写的nil的表亲,不经常出现,但是至少值得注意。
关于nil
新分配的NSObjects开始生命周期的内容设置为零。这意味着所有对象拥有的指向其他对象的指针开始为“nil”。因此,没有必要在init方法中设置self.(association) = nil。
或许nil最值得注意的行为是,能够给他发送消息。
其他语言,例如C++,这种行为会毁坏你的程序。但是,对于Object-C而言,调用nil的方法会返回零值。这极大地简化了表达式,因为在做任何事情之前,省却了nil检查。
// For example, this expression...
if(name!=nil&&[nameisEqualToString:@"Steve"]){...}
// ...can be simplified to:
if([nameisEqualToString:@"steve"]){...}
知道了Objective-C中nil的工作原理使这种便利性成为一种特性。并且在程序中这不是潜在的Bug。为了确保不出现nil取值不合法的情况,要么通过静静地尽早检查和返回失败,要么添加NSParameterAssert来抛出异常。
NSNull:表示空的某种东西
为了绕过集合,例如NSArray和NSDictionary,不能包含nil值的局限性,NSNull在Foundation和其他框架中普遍采用。你可以认为NSNull封装了NULL或nil值以便在集合中使用。
NSMutableDictionary*mutableDictionary=[NSMutableDictionarydictionary];
mutableDictionary[@"someKey"]=[NSNullnull];// Sets value of NSNull singleton for `someKey`
NSLog(@"Keys: %@",[mutableDictionaryallKeys]);// @[@"someKey"]
综上所述,每一个Objective-C程序员都应该知道这四个值可以表示“空”:
|