当该对象上某个方法,而该对象没有实现该方法,就会报异常。
objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,如果,在最顶层的父类中依然找不到相应的方法时,程序在运行时会挂掉并抛出异常unrecoginzed selector sent to XXX .但是在这之前,objc的运行时会给出三次拯救程序崩溃的机会:
Method resolution
objc运行时调用+resolveInstanceMethod:或者+resloveClassMethod ;让你有机会提供一个函数的实现。如果你实现了一个函数的实现。如果你添加了函数并返回yes,那运行时系统就会重新启动一次消息发送的过程,如果reslove返回NO,运行时就会移到下一步,消息转发
Fast forwarding
如果目标对象实现了-forwardingTargetForSelector;Runtime这时就会调用这个方法,给你这个消息转发给其他对象的机会。只要这个方法返回的不是nil和self,整个消息发送就会被重启,当然发送的对象会变成你转发的对象。否则,就会继续Normal Fowarding。只是为了区别下一步的转发机制。因为这一步不会创建新的独享,但下一步转发会创建一个NSINvocation对象,所以相对更快点。
Normal forwarding
这一步是Runtime最后一次给你挽救的机会。首先它会发送-methodSignatureForSelector,消息获得函数的参数和返回值类型。如果--methodSignatureForSelector返回nil,runtime则会发出-doesNotRecognizeSelector:消息,程序也就会挂掉。如果返回一个函数签名,runtime就会创建一个NSInvocation对象并发送forwardInvocation给目标
一个objc对象如何进行内存布局
所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间
每一个对象内部都有一个isa指针,指向它的类对象,类对象中存放着
1)对象的方法列表
2)成员变量的列表
3)属性列表
类对象内部也有一个isa指针指向元对象(meta class),内部存放类方法列表类对象内部有一个superclass的指针,指向它的父类对象。
1)根对象就是NSobject ,它的superclass是nil
2)类对象既然称为 对象,那它也是一个实例。类对象中也有一个isa指针指向它的元类(metaclass),类对象是元类的实例。元类内部存的是类方法列表,根元类指针指向自己,superclass指针指向nsobject
对象