面试题答案
一键面试元类在Objective-C消息转发机制中的角色
- 类与元类的关系基础:在Objective-C中,每个类都有一个与之关联的元类(meta - class)。类对象存储着实例方法列表,而元类存储着类方法列表。元类的isa指针指向根元类,根元类的isa指针指向自身,形成一个闭环。
- 消息转发流程中元类的作用:当向一个对象发送一条它本身并未直接实现的消息时,元类在整个消息转发流程中有着重要作用。
- 动态方法解析阶段:
- 当对象接收到未实现的消息时,首先进入动态方法解析阶段。运行时系统会向对象所属的类发送
+resolveInstanceMethod:
消息(如果是实例方法)或+resolveClassMethod:
消息(如果是类方法)。 - 对于类方法,类方法存储在元类中,所以此时元类参与其中。如果元类实现了
+resolveClassMethod:
方法,并且在该方法中动态添加了对应的类方法实现,那么消息转发就可以成功完成,对象就能响应这个原本未实现的类方法。
- 当对象接收到未实现的消息时,首先进入动态方法解析阶段。运行时系统会向对象所属的类发送
- 备用接收者阶段:
- 如果动态方法解析阶段没有处理该消息,就进入备用接收者阶段。运行时系统会向对象发送
-forwardingTargetForSelector:
消息。 - 这里虽然主要是对象本身来决定是否有备用接收者,但元类间接参与。因为对象的类信息(包括元类相关信息)决定了对象的行为逻辑。如果对象决定返回一个备用接收者,那么这个备用接收者的类(及其元类结构)会影响后续消息的处理。如果备用接收者能够处理该消息,那么消息转发成功。
- 如果动态方法解析阶段没有处理该消息,就进入备用接收者阶段。运行时系统会向对象发送
- 完整的消息转发阶段:
- 如果备用接收者阶段也没有处理该消息,就进入完整的消息转发阶段。运行时系统会创建一个
NSInvocation
对象,该对象封装了原始的消息发送信息。 - 然后向对象发送
-methodSignatureForSelector:
消息获取方法签名。如果对象所属的类没有实现-methodSignatureForSelector:
方法,元类信息会影响查找过程,因为元类与类有继承关系(元类的超类是类的超类的元类),可能从元类继承的相关方法中找到方法签名。 - 接着运行时系统向对象发送
-forwardInvocation:
消息,传入NSInvocation
对象。在这个方法中,开发者可以手动处理消息转发,例如将消息转发给其他对象等。如果这个阶段也没有成功处理消息,最终会导致unrecognized selector sent to instance
异常。
- 如果备用接收者阶段也没有处理该消息,就进入完整的消息转发阶段。运行时系统会创建一个
- 动态方法解析阶段: