iOS消息机制相关

(1)OC中给nil对象发送消息程序是否会crash?

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,变为空指针。

注意:

在使用一个对象前判断它是否为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的场景下,例如可变数组中,想插入一个空对象时。

(2)objc向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?    

objc_msgSend()是[obj foo]的具体实现。在动态编译时,[obj foo]会被转意为:objc_msgSend(obj, @selector(foo))

先去obj对应的类中找方法;找缓存,找不到时去找方法列表;再找父类,以此向上传递;最后找不到则转发。

(3)什么情况会报unrecognized selector异常?

调用某个对象方法时,当前类中无此方法,那么去父类查找,向上直到NSObject。若依旧找不到,则会报此错误。

若没有实现某个方法时,会调用_objc_msgForward进行方法转发。方法对应的IMP没找到,会返回该函数的IMP去执行。

在崩溃前,objc运行时会给出三次拯救崩溃的机会。

+(bool)resolveInstanceMethod:(sel){

//第一次找不到时,会自动调用该方法,用来给程序添加一个新方法并执行

}

-(id)forwardingTargetForselector:(sel)aselctor{

//当系统调用上一个方法后未能实现添加新方法,这是系统提供一个将SEL转给其他对象的机会

}

(NSMethodSigature *)methodSignatrueForseletor:(sel)aselector{

//当上一个方法返回nil或self时,进入该方法,返回一个方法签名,并由forwardInvocation:去执行

}

-(void)forwardInvocation:(NSInvocation *)anInvocation{

//若上面方法不返回nil,则在这里调用自己对象的其他方法,也可以调用其它函数,以及多个不同对象的多个方法

}

(5)一个objc对象如何进行内存布局?(有父类时)

所有的父类成员变量以及自己的都会存放在对象所对应的存储空间中

每个对象都有一个isa指针,指向他的类对象,类对象中存放着本身对象的方法列表;成员变量的列表;属性列表。类对象内容也有一个isa指针指向元对象,元对象内部存放的是类方法列表,类对象有一个superclass指针,指向父类对象。

根对象是NSObject,superclass指针指向nil

类对象也是实例,也有一个isa指针指向他的元类,即类对象的元类实例,元类内部存放的是类方法列表,根元类的isa指针指向自己,superclass指针指向NSObject类。

(6)_objc_msgForward函数作用,直接调用将会发生什么?

当对象没有实现某个方法时,会调用该函数进行方法转发。

直接调用该方法,就算实现了要调用的方法,也不会被调用,会直接走消息转发步骤

转发自https://www.jianshu.com/p/38f013075e9a

你可能感兴趣的:(iOS消息机制相关)