在看消息转发之前,我们先看一段代码,调用一个 nil 对象方法会咋样?
//Person.h
@interface Person : NSObject
//年龄
- (int)age;
@end
//Person.m
@implementation Person
- (int)age
{
return 18;
}
@end
//调用地方
Person * p = nil;
NSLog(@"my age is :%d",[p age]);
要想几个问题,1,会 crash 吗? 为什么,2, log出来的值是18吗?
答案就是不会 crash 因为OC的函数调用都是通过objc_msgSend进行消息发送来实现的,相对于C和C++来说,对于空指针的操作会引起Crash的问题,而objc_msgSend会通过判断self来决定是否发送消息,如果self为nil,那么selector也会为空,直接返回,所以不会出现问题。视方法返回值,向nil发消息可能会返回nil(返回值为对象)、0(返回值为一些基础数据类型)或0X0(返回值为id)等,同时不能输出18. 使用clang -rewrite-objc xxxx.m 可以把一个类编译.
在如下代码,在MRC下创建别一个 p2 对象
Person * p2 = [[Person alloc] init];
[p2 release];
//PS:XXXXXX 对一个object做了release之后,这个object的引用计数会立即减1,但这个object并不一定就立即被free了。直到其引用计数变成0的时候,它才可能真正被free掉在没 free 之前 调用age前加一句log 就是等free了再调用 age 才会crash. 使用 sleep(10)效果是一样的,是不是有同学有时候加一句log后就有不同的运行结果可以查看是不是同样问题
NSLog(@"p2 count %ld