MST

星途 面试题库

面试题:Objective-C的Runtime消息转发机制与关联对象原理

详细阐述Objective-C的Runtime消息转发机制的完整流程,包括动态方法解析、备用接收者、完整的消息转发。同时说明关联对象在Runtime中的实现原理,以及它在实际开发中的应用场景。
38.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

Objective-C的Runtime消息转发机制完整流程

  1. 动态方法解析
    • 当向一个对象发送一条它无法识别的消息时,首先进入动态方法解析阶段。
    • 对于实例方法,运行时系统会调用类方法 + (BOOL)resolveInstanceMethod:(SEL)sel,开发者可以在这个方法中动态添加方法实现。例如,可以使用 class_addMethod 函数动态为类添加一个实例方法。
    • 对于类方法,运行时系统会调用 + (BOOL)resolveClassMethod:(SEL)sel,同样可以在这个方法中使用 class_addMethod 动态添加类方法的实现。
  2. 备用接收者
    • 如果动态方法解析阶段没有处理消息,那么进入备用接收者阶段。
    • 运行时系统会调用 -(id)forwardingTargetForSelector:(SEL)aSelector 方法,在这个方法中,开发者可以返回一个能处理该消息的对象。如果返回非 nil 对象,那么消息会被转发给这个对象处理;如果返回 nil,则进入完整的消息转发阶段。
  3. 完整的消息转发
    • 首先,运行时系统会创建一个 NSInvocation 对象,它封装了消息的参数、选择子和目标对象等信息。
    • 然后调用 -(void)forwardInvocation:(NSInvocation *)anInvocation 方法,在这个方法中,开发者可以手动指定将消息转发给哪个对象处理。可以通过 [anInvocation setTarget:newTarget] 重新设置消息的目标对象,然后调用 [anInvocation invoke] 来触发消息的执行。
    • 如果 forwardInvocation: 方法没有处理消息,那么运行时系统会调用 -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法来获取方法签名。如果这个方法返回 nil,则会抛出 unrecognized selector sent to instance 异常;如果返回有效的方法签名,那么会再次调用 forwardInvocation: 方法来处理消息。

关联对象在Runtime中的实现原理

  1. 实现原理
    • 关联对象是通过 objc_setAssociatedObjectobjc_getAssociatedObjectobjc_removeAssociatedObjects 这几个函数来实现的。
    • 每个对象都有一个独立的 AssociationsManager,它管理着一个全局的 AssociationsHashMap。这个哈希表以对象的内存地址作为键,以另一个哈希表 ObjectAssociationMap 作为值。
    • ObjectAssociationMap 以关联对象的 key(通常是一个 NSString 或者 void * 类型的唯一标识)作为键,以 ObjectAssociation 结构体作为值。ObjectAssociation 结构体存储了关联对象的引用策略(如 OBJC_ASSOCIATION_ASSIGNOBJC_ASSOCIATION_RETAIN_NONATOMIC 等)和关联对象本身。
  2. 应用场景
    • 给分类添加属性:在Objective - C中,分类不能直接添加实例变量,但可以通过关联对象为分类添加属性。例如,为 UIView 分类添加一个自定义的属性来存储额外的数据。
    • 临时附加数据:在某些情况下,需要为对象临时附加一些数据,而不需要在类的定义中添加属性。比如在视图控制器的跳转过程中,临时为某个视图控制器对象附加一些传递的数据。