面试题答案
一键面试协议的实现原理
- 数据结构:在Objective - C底层,协议本质上是一个
objc_object
结构体,其内部包含了协议的元数据,如协议名称、所声明的方法列表等信息。 - 类对协议的遵循:当一个类声明遵循某个协议时,会在类的元数据中记录所遵循的协议列表。这使得运行时系统能够知晓该类实现了哪些协议的方法。
协议方法的调用与解析
- 方法调用:当通过遵循协议的对象调用协议方法时,运行时系统会首先在对象所属类的方法列表中查找该方法的实现。
- 动态方法解析:如果在类的方法列表中未找到,运行时会进入动态方法解析阶段。它会尝试通过
+ (BOOL)resolveInstanceMethod:(SEL)sel
(实例方法)或+ (BOOL)resolveClassMethod:(SEL)sel
(类方法)方法来动态添加方法实现。 - 备用接收者:若动态方法解析未成功,运行时会寻找备用接收者,即调用
- (id)forwardingTargetForSelector:(SEL)aSelector
方法,看是否能找到其他对象来处理该消息。 - 完整的消息转发:若仍未找到处理该消息的方式,会进入完整的消息转发流程,调用
- (void)forwardInvocation:(NSInvocation *)anInvocation
方法,开发者可以在此处手动构建消息转发逻辑。
多个类遵循同一协议且方法实现不同时的调度
- 基于对象类型:运行时系统根据对象的实际类型来决定调用哪个类的协议方法实现。因为每个类都有自己独立的方法列表,即使它们遵循同一个协议,不同类对协议方法的实现也会被独立存储在各自的方法列表中。
- 动态绑定:在运行时,消息发送机制会动态地根据对象的实际类型找到对应的方法实现。例如,假设有类
ClassA
和ClassB
都遵循协议ProtocolX
,并且都实现了协议中的methodInProtocol
方法。当ClassA
的实例调用methodInProtocol
时,运行时会根据该实例是ClassA
类型,去ClassA
的方法列表中找到其对methodInProtocol
的实现并调用;同理,当ClassB
的实例调用时,会从ClassB
的方法列表中查找并调用其实现。