绪:静态绑定:编译时期便能确定所要调用的函数。动态绑定:运行时期才能确定所要调用的函数。
一. 消息传递机制。
1.消息:OC的类调用一个实类方法或类方法。即:向该类发送了消息。消息就是这个方法。是由接收者(方法的调用者),选择子( @selector(setDate:)),参数组成。
注意点:发送给某个类的全部消息,都是要由“动态消息派发系统(Dynamic Message Dispatch System)”来处理。
2.消息的传递:OC的类调用一个实类方法或类方法。编译器会自动解读为标准的C语 言函数:
①objc_msgSend(id,@selector(...),parameter);parameter个数不定。
有:objc_msgSendSuper(发送父类的消息),objc_msgSend_stret(处理:待发送的消息返回的是一个结构体,前提CPU寄存器能够容纳下返回的结构体,否则便会由另一个函数执行派发,那个函数会通过分配在栈上的某个变量来处理消息返回的结构体。),objc_msgSend_fpret(处理:消息返回的是一个浮点数,可交由此函数处理)。
objc_msgSend函数会依据接收者和选择子的类型来调用适当的方法。每个类都有一张表格(方法列表),表格中的指针都会指向这种函数(OC类中方法的C语言函数),而选择子的名称便是查表时的“键”,objc_msgSend,会通过这张表进行查找并跳转实现方法。若是在当前类的方法列表中找到合适的方法便会跳转方法的实现。否则就会沿着继承体系往上找,找到合适的方法后再跳转。(这里跳转到实现代码这一操作利用了“尾调用优化”技术。即:尾递归优化。)
否则....
当前对象收到的消息无法解读(方法列表中无法获取)进入消息转发机制。
二.消息的转发机制。
消息转发机制分为两个阶段:
第一个阶段:首先询问当前的接收者所属的类,能否动态的添加一个方法去处理当前这个未知的方法子。这个叫做:动态方法解析。
尚未实现的方法是类方法则调用:
② +(BOOL)resolveClassMethod:(SEL)sel
尚未实现的方法是实例方法则调用:
+(BOOL)resolveInstanceMethod:(SEL)sel
它们的返回值表示的是:是否能动态增加方法去处理这个位置的选择子方法。
第二个阶段:涉及“完整的消息转发机制”。若第一阶段执行完毕,那么当前接收者,就再无法通过动态增加方法,去响应当前的未知选 择子的消息了。此时,objc运行时系统会请求接收者以其他手段来处理与消息相关的方法调用。
分为两步:
第一步:查看接收者有没有其他对象能够处理这个消息,若有则系统会把消息转发给那个对象。完毕
③ -(id)forwardingTargetForSelector:(SEL)aSelector---返回“备援消息接收者”去处理这个消息,切记返回当前对象会造成死循环。
否则...
第二步:启动完整消息转发机制。运行时系统会通过- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector获取转发机制中的方法签名(获取与消息有关的一切)全部封装到NSInvocation对象中。通过- (void)forwardInvocation:(NSInvocation *)anInvocation返回,并给接收者最后一次处理消息的机会,令其设法解决当前还未处理的消息。
据API描述:要响应您的对象本身无法识别的方法,除了forwardInvocation:之外,您必须重写 methodSignatureForSelector:。 转发消息的机制会使用从methodSignatureForSelector获得的信息:创建要转发的NSInvocation对象。 您覆盖的方法签名方法必须为给定的选择器(or选择子)提供适当的方法签名。
④ - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
签名信息对象(NSMethodSignature*)的方法中对于:[NSMethodSignature signatureWithObjCTypes:"v@:@"];@表示一个对象 :表示一个方法名 v表示void 方法描述的格式为——返回值+当前对象+方法名+参数 没有参数就不写。详细
⑤ - (void)forwardInvocation:(NSInvocation *)anInvocation