OC想nil发送消息,是不会崩溃的。
OC的函数调用都是通过objc_msgSend进行消息发送来实现,相对于C/C++来说,操作空指针引起crash问题,objc_msgSend通过判断self来决定是否发送消息,self为nil,那么selector也为空,直接返回,所以不会崩溃。向nil发消息可能会返回nil(对象)、0(基础数据类型)或0x0(id类型),但对[NSNull null]对象发消息时,会造成crash,因为NSNull类只有一个null方法。若对象已被释放,引用计数为0,去调用方法肯定也会crash,访问了野指针。那么,安全的做法就是将释放的对象置为nil,变为空指针。
小tips:
在使用一个对象前判断它是否为nil,好处:1.降低时间复杂度,当为nil就不需要对其发送消息,节省资源 2.切换语言时不容易出错
关于nil,定义为null pointer to object-c class,指的是一个类指针为空,本质是(class)0,OC类的字面为零值。
关于null,定义为null pointer to primitive type or absence of data,指的是一般基础数据类型为空,可以给任意指针赋值,本质是(void *)0,是C指针的字面0值。尽量不用null初始化OC对象,null主要针对基础数据类型。
关于NSNull,包含了唯一方法+(NSNull *)null,是一个对象,用于表示零值的单独对象。主要用于不能使用nil的场景下,例如可变数组中,想插入一个空对象时。
+(bool)resolveInstanceMethod:(sel){
//第一次找不到时,会自动调用该方法,用来给程序添加一个新方法并执行
}
-(id)forwardingTargetForselector:(sel)aselctor{
//当系统调用上一个方法后未能实现添加新方法,这是系统提供一个将SEL转给其他对象的机会
}
//当上一个方法返回nil或self时,进入该方法,返回一个方法签名,并由forwardInvocation:去执行
}
-(void)forwardInvocation:(NSInvocation *)anInvocation{
//若上面方法不返回nil,则在这里调用自己对象的其他方法,也可以调用其它函数,以及多个不同对象的多个方法
}
类对象也是示例,也有一个isa指针指向他的元类,即类对象的元类实例,元类内部存放的是类方法列表,根元类的isa指针指向自己,superclass指针指向NSObject类。
类方法属于类对象;
类方法只能通过类对象调用;
类方法中的self是类对象;
类方法中不能访问成员变量;
类方法可以调用其他的类方法;
类方法中不能直接调用对象方法
实例方法:
实例方法是属于实例对象的;
实例方法只能通过实例对象调用;
实例方法中self是实例对象;
实例方法中可以访问成员变量;
可直接调用实例方法;
可直接调用类方法
指针查找
对象的isa指向类,类的isa指向元类(也是类,也是对象),元类isa指向元类的根类,最终根元类的isa指向它本身,形成一个封闭的内循环。isa是帮助一个对象找到他的方法。
当对象没有实现某个方法时,会调用该函数进行方法转发。
直接调用该方法,就算实现了要调用的方法,也不会被调用,会直接走消息转发步骤