iphone开发cocoa中nil,NSNull,Nil的使用区别

1,nil的简单定义

你可能还不知道nil在Objective-C中是什么意思。为了避免混乱,先简单定义一下nil:

nil表示一个对象指针不指向任何对象时的值。

如果你熟悉其它源自C语言的语言,你可能会问:NULL和nil是一样的吗?

答案是基本一样。NULL可以用在C语言的各种指针上,而nil用在Objective-C的对象指针上。如果你在xcode上右击nil,查看定义,你会发现:nil、NULL和__DARWIN_NULL全都定义成一个值,那就是(void *)0。

Objective-C还定义了一个常量Nil。注意这个N是大写的。它的值和nil是一样的。它用于类指针。但在实际使用的时候,都使用nil就可以了。

2,初始化时,任何东西都是0

在Objective-C语言中,新alloc出来的对象的实例变量(除了isa)会被设置成0。这与C语言的calloc比较像。

这意味着一个对象中所有指向其它对象的指针已经被设置成nil了。所以可以不设特意将实例变量初始化为nil,false,0什么的。

3,可以向nil发送消息

在Objective-C中,你可以向nil发送任何消息。这一点和C/C++不太一样,如果向NULL发送消息的话,程序就会崩溃了。向nil发送消息什么也不会做,返回值会是0。因此下面的代码:

if(myObject==nil|| ![myObjectisEqualTo:anotherObject]){

...
}

可以简写成:

if(![myObject isEqualTo:anotherObject]){

...

}

向nil发送消息有一些缺点:
1,当期待的返回值类型的大小,小于或等于一个pointer的大小时,是不会有问题。或者返回类型是long long、double、或者是struct,也没有问题。对long long、double、和struct的支持是从mac os 10.5开始的。
2,有时候nil在代码中可能表示一个特殊的情况。
3,nil有时会让程序debug变得困难。本来一个变量不应该是nil。这样的错误很难被发现。

/##########################################################################/

补充:

 向nil发送消息    在Objective-C中向nil发送消息是完全有效的——只是在运行时不会有任何作用。Cocoa中的几种模式就利用到了这一点。发向nil的消息的返回值也可以是有效的:
    • 如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如:Person * motherInlaw = [ aPerson spouse] mother]; 如果spouse对象为nil,那么发送给nil的消息mother也将返回nil。
    • 如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者long long的整型标量,发送给nil的消息将返回0。
    • 如果方法返回值为结构体,正如在《Mac OS X ABI 函数调用指南》,发送给nil的消息将返回0。结构体中各个字段的值将都是0。其他的结构体数据类型将不是用0填充的。
    • 如果方法的返回值不是上述提到的几种情况,那么发送给nil的消息的返回值将是未定义的。

既然给空指针发送消息不会崩溃,那么我们是否还有必要在发消息前判断一下指针是否为空?

在知乎上有人问到说,斯坦福课程里推荐不用判断 nil。但是有时候不判断 nil 又会导致程序崩溃,例如往 NSArray 里插入一个 nil 的情况。

以下是我的回答:

不管斯坦福怎么说,我的建议是如果这个指针可能为空,那么用之前都做一下判断。

为什么这么建议呢?

首先,最实际的理由是,给空指针发消息是非常慢的,而做一下 if 判断是否为空是非常快的操作。
这个速度上的差别是百倍这个单位的。

为什么呢?因为给 nil 发消息这件事情是在运行时判断的,而系统也并非简单的丢掉这个消息,系统还需要判断这个消息是否需要返回值,如果需要,还要判断返回值的类型:如果返回指针、数字、真伪等,则返回 0,如果返回的是 OS 定义过的数据结构,那么会返回一个被填充上 0 的结构回来,如果返回的是其它类型,则系统会返回一个未定义的类型回来。而一个 if,则能够直接跳过这些运行时的处理。

我做过一个实验:

分别是两个100万次的循环,其中一个给 nil 对象发送了 100万次消息,另外一个循环在发消息前,会判断一下该对象是否为空。

实验的结果是两个循环的执行时间相差了200多倍。这还是消息中没有传任何参数的情况。

这就好像我们不建议用 try cache 来做本可以用 if else 判断掉的错误处理一样,因为开销太大。

另外,“给空指针发消息不会崩溃”是语言特性,是为了防止人为失误导致程序崩溃的“保险”机制。我们写代码时应该尽量避免依赖语言特性的写法,因为这不利于代码(逻辑)移植,语言特性本身也是会变化的(哪怕变化的可能性为零)。

最后,这能养成一个好习惯,培养出一个好的思维方式。上述的这种遇到“错误”也让程序继续跑下去的语言特性本身就是有争议的,虽然给 nil 发消息不会崩溃,但也正是由于程序不会崩溃,当你的代码写错时你也无法察觉到,你的程序有可能会进入一个你完全没有预期到的状态,看似一切正常,但返回的结果却是完全错误的。而写代码时花1秒钟加一个简单的 if 判断,就能够清楚地看出哪个指针是可能为空的,这些信息在分析代码问题的时候是非常宝贵的。

/##########################################################################/

4,NSNull

NSNull对象是nil的代替者。主要用在使用一些容器类的时候使用,比如NSArray,NSSet,NSDictionary。因为这些容器类是不能包含nil的。

你可以试着将一个NSNull对象插入到自己的容器对象中。但是,它的真正用途是cocoa自动为你添加时,看看下面的例子:

Objective-C

1

NSArray *namesOfObjects=[arrayOfObjects valueForKey:@"name"];

valueForKey:方法使用KVC将arrayOfObjects 这个数组中每个对象的”name”取出,生成一个NSArray。如果所有的name属性都是nil,就会返回一个NSNull的对象。

注意:最好测试一下是不是返回NSNull。NSSet使用KVC的时候就不会创建NSNull对象。

5,设置NSMutableDictionary的值为nil

NSArray *namesOfObjects=[arrayOfObjectsvalueForKey:@"name"];

上面的代码会抛出异常。如果你要将一些对象插入到NSMutableDictionary当中的话,又不知道这些对象中有没有nil。所以代码要像下面这样来写:

NSMutableDictionary  *newDictionary=[NSMutableDictionary dictionary];

id firstObject=[source getFirstObject];

if(firstObject)

{

[newDictionary setObject:firstObject forKey:@"firstObjectKey"];

}

// ... and so on for all other objects

如果key是String的,可以使用NSMutableDictionary的KVC方法,这样写就可以了。

NSMutableDictionary  *newDictionary=[NSMutableDictionary dictionary];

[newDictionary setValue:[source getFirstObject] forKey:@"firstObjectKey"];

// ... and so on for all other objects

注意用setValue:forKey:代替setObject:forKey:方法,setValue:forKey:方法首先先测试value,看是不是nil。如果是nil,就会像调用了removeObjectForKey:了一样。如果dictionary里没有对象,那就什么也不做。

KVC需要string的键,所以如果一个dictionary的键不是string的,上面的方法就不行了。

时间: 2024-10-19 03:48:09

iphone开发cocoa中nil,NSNull,Nil的使用区别的相关文章

step 5 NULL & nil & Nil & NSNULL

NULL & nil & Nil & NSNULL nil 是 OC 的,空对象,地址指向 空(0) 的对象 在 OC 中,可以给空对象发送任何消息,不会出现错误 NULL 是 C 的,空地址,地址的数值是 0,是一个长整数 表示地址是空 NSNull 用于解决向 NSArray 和 NSDictionary 等集合中添加空值的问题 值 定义 NULL (void *)0 C指针的字面零值 nil (id)0 Objective-C对象的字面零值 Nil (Class)0 Obje

OC中Nil、nil、NULL、NSNull、class、Class

原先对此很迷惑,但是在网上看了很多文章后略有所得. 1.Class和class class指类,类是对象(object)的类型.比如 NSString *str = [[NSString alloc]init]: NSString就是一个class,是对象str的类型. Class指类的类型,比如:Class aclass = [NSString class]: aclass就是一个类,就是NSString这个类,而Class就势aclass的类型. 2.Nil.nil.NSNull.NULL

Objective-C 中 NULL、nil、Nil、NSNull 的定义及不同

来源:XcodeMen(康祖彬) 链接:http://www.jianshu.com/p/5d7033b15052 本文由我们团队的 康祖彬 童鞋撰写,这是他的个人主页:https://kangzubin.cn. 理解"不存在"的概念不仅仅是一个哲学的问题,也是一个实际的问题.我们是有形宇宙的居民,而原因在于逻辑宇宙的存在不确定性.作为一个逻辑系统的物理体现,计算机面临一个棘手的问题,就是如何用"存在"表达"不存在".–摘自 NSHipster

iOS中nil,NULL,Nil,NSNull的区别

最近心情不太好,往往心情不太好的时候喜欢学点东西,写点东西,具体因为什么心情不太好在这里就不给大家爆料了哦! 言归正传: 1.nil定义一个实例为空, 指向oc中对象的空指针. 注意:当release一个对象的同时将该对象赋值为nil,这样确保安全性. 2.NULL在C语言中常用来表示一个空值. 注意:在Objective-C里,nil对象被设计来跟NULL空指针关联的.他们的区别就是nil是一个对象,而NULL只是一个值.而且我们对于nil调用方法,不会产生crash或者抛出异常. 3.Nil

iOS 中nil,Nil,NULL,NSNull的区别

类与对象的概念 类是对同一类事物高度的抽象,类中定义了这一类对象所应具有的静态属性(属性)和动态属性(方法). 对象是类的一个实例,是一个具体的事物. 类与对象是抽象与具体的关系. 类其实就是一种数据类型,它的变量就是对象. nil.Nil.NULL.NSNull的区别 nil:指向一个对象的空指针 Nil:指向一个类的空指针 NULL:指向其他类型(如:基本类型.C类型)的空指针 NSNull:通常表示集合中的空值 举例: NSURL *url = nil; Class class = Nil

Objective-C中release和nil的关系

(iphone/ipad)浅谈Objective-C中release和nil的关系 分类: iPhone/iPad开发技术2011-12-09 01:40 2515人阅读 评论(4) 收藏 举报 uiviewcrashnull终端 注意到经常有一个这样的问题:某指针对象先release后=nil,这里后跟个=nil有什么作用?不写行不行? 简单一点说是,release是用来释放内存,nil是将对象指针设为null,nil本身对内存没什么影响,但他处理指针,尤其是避免野指针倒是很有必要. 举一个例

iphone开发数组排序(数组中包括字典)

原文地址 http://blog.csdn.net/bihailantian1988/article/details/8433812 iphone开发数组排序(数组中包括字典) 1.普通数组排序: NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"0",@"8",@"6",@"1",nil]; NSArray *sortedArray = [arr sortedA

ios nil null Nil NSNull区别

nil.Nil.NULL.NSNull的区别 nil:指向一个对象的空指针 Nil:指向一个类的空指针 NULL:指向其他类型(如:基本类型.C类型)的空指针 NSNull:通常表示集合中的空值 举例: NSURL *url = nil; Class class = Nil; int *pointerInt = NULL; NSArray *array = [NSArray arrayWithObjects:[[NSObject alloc] init], [NSNull null], [[NS

[swift、oc]浅聊nil、Nil、NULL、NSNull的区别

我们都知道nil.Nil.NULL.NSNull都表示为空但是究竟有什么区别,相信大家也很少关注.今天我们就浅聊一下这几个空的区别 1.nil nil一般是指把一个对象置空,既完全是一个空对象,完全从内存中释放. 2.Nil Nil和nil基本没有任何区别,也可以说只要是可以使用nil的地方都可以使用Nil,反之亦然.但是作为程序猿,我们应该更加严谨一些.nil和Nil的区别在于,nil表示置空一个对象,二Nil表示置空一个类. 3.NULL 大家都知道oc 是基于c的,并且oc是完全兼容c的,