nil / Nil / NULL / NSNull ? 傻傻分不
NULL算是属于C语言中的空指针。
Objective-C在C的表达不存在的基础上增加了nil。nil是一个指向为空的对象指针
。虽然它在语义上与NULL不同,但是在技术层面上来说,它们是相等的。
在Foundation/NSObjCRuntime.h中,Nil被定义为指向为空的类指针
,这个Nil并不经常会使用到,但也值得注意。
在框架层面,Foundation定义了NSNull,即一个类方法+null,它返回一个单独的NSNull对象。NSNull与nil以及NULL不同,因为它是一个实际的对象,而不是一个空值。
nil
刚被分配的NSObject的内容被设置为空。也就是说那个对象所有的指向其他对象的指针都从nil开始,所以在init方法中将变量初始化为 nil 的表达是没有必要的。nil最为显著的特点其实是它虽然为空,但是当向nil发送消息时,程序不会有异常,会继续执行下去
。
// 举个例子,这个表达
if (name != nil && [name isEqualToString:@"Tom"]) { ... }
// 可以简化为:
if ([name isEqualToString:@"Tom"]) { ... }
需要注意Array和Dictionary使用nil的情况。在使用NSArray的+ arrayWithObjects:
和-initWithObjects:
以及NSDictionary的+ dictionaryWithObjectsAndKeys:
和 - initWithObjectsAndKeys:
这些标记为 NS_REQUIRES_NIL_TERMINATION
的方法时,nil是被当成最后一个参数的,出现在nil后面的参数都会被忽略掉。比如:
NSArray *arr = [ NSArray arrayWithObjects:@ 1 , @ 2 , nil , @ 3 ];
NSLog ( @"arr = %@" , arr);
这个数组对象arr其实只有@1和@2两个元素,@3已经被截掉了。
Nil
nil表示空的实例(instance),而这个开头字母大写的Nil则表示空的类(class),判断某个Class是否为空,语意上应该用Nil。
NULL
绝大多数情况下,nil、Nil和NULL可以代替使用,但是在语意上,当某个API想要传入某个指针(void *),而不是id类型时,最好还是传入NULL,以此保持了Objective-C严谨的定义。比如NSArray的这个API,argument要求的是id,所以传入nil会比较好。
- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(nullable id)argument
而像NSMutableArray的sortUsingFunction:context:
- (void)sortUsingFunction:(NSInteger (*)(ObjectType, ObjectType, void * __nullable))compare context:(nullable void *)context;
在这里,context传入NULL会比传入nil好。
NSNull
NSNull在Foundation和其它框架中被广泛的使用,以解决如NSArray和NSDictionary之类的集合不能有nil值的缺陷。
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionary];
mutableDictionary[@"someKey"] = [NSNull null];
NSLog(@"Keys: %@,mutableDictionary = %@", [mutableDictionary allKeys],mutableDictionary);
打印的结果如下:可以看出字典mutableDictionary有一个元素,该元素的key值为someKey,其对应的value为null。
![](https://img.haomeiwen.com/i1338319/f82ea445b16ec45c.png)
如果将上面的代码改为:
...mutableDictionary[@"someKey"] = nil;
NSLog(@"Keys: %@,mutableDictionary = %@", [mutableDictionary allKeys],mutableDictionary);
此时,打印出来的Keys和mutableDictionary的值是空的,什么也没有!所以NSNull在这个字典里充当一个占位符
,表示没有
。
NULL、nil、Nil、NSNull的区别
标志 | 值 | 含义 |
---|---|---|
NULL | (void *) 0 | C指针的字面零值 |
nil | (id) 0 | Objective-C对象的字面零值 |
Nil | (Class ) 0 | Objective-C类的字面零值 |
NSNull | [NSNull null] | 用来表示零值的单独的对象 |