MST

星途 面试题库

面试题:Objective-C 中消息转发机制的主要步骤是什么

请详细阐述 Objective-C 消息转发机制在运行时经历的主要步骤,包括动态方法解析、备用接收者以及完整的消息转发流程。
30.8万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

动态方法解析

  1. 类方法解析:当向一个对象发送一条它无法识别的消息时,运行时首先会调用类方法 + (BOOL)resolveClassMethod:(SEL)sel。如果在这个方法中为该 SEL 动态添加了实现,消息转发就结束,对象能够响应这个消息。例如:
+ (BOOL)resolveClassMethod:(SEL)sel {
    if (sel == @selector(someClassMethod)) {
        class_addMethod(self, sel, (IMP)someClassMethodImplementation, "v@:");
        return YES;
    }
    return [super resolveClassMethod:sel];
}
  1. 实例方法解析:如果类方法解析没有处理该消息,运行时会调用实例方法 + (BOOL)resolveInstanceMethod:(SEL)sel。同样,如果在此方法中为 SEL 动态添加了实现,消息转发结束。例如:
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(someInstanceMethod)) {
        class_addMethod(self, sel, (IMP)someInstanceMethodImplementation, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

备用接收者

  1. 如果动态方法解析阶段没有处理该消息,运行时会进入备用接收者阶段。它会调用对象的 - (id)forwardingTargetForSelector:(SEL)aSelector 方法。
  2. 在这个方法中,对象可以返回一个能够处理该 SEL 的其他对象。如果返回非 nil 对象,那么运行时会将消息发送给这个备用接收者,消息转发流程结束。例如:
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(someMethod)) {
        return someOtherObject;
    }
    return nil;
}

完整的消息转发流程

  1. 动态方法解析:运行时首先尝试在类的方法列表中查找方法实现,如果找不到,会触发动态方法解析,先尝试类方法解析 + (BOOL)resolveClassMethod:(SEL)sel,再尝试实例方法解析 + (BOOL)resolveInstanceMethod:(SEL)sel
  2. 备用接收者:若动态方法解析未处理消息,运行时调用 - (id)forwardingTargetForSelector:(SEL)aSelector 寻找备用接收者。若找到,则将消息转发给备用接收者。
  3. 完整转发:如果备用接收者也未处理消息,运行时会进入完整转发阶段。首先调用 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector,该方法需要返回一个 NSMethodSignature 对象,描述方法的参数和返回值类型。如果返回 nil,则会调用 - (void)doesNotRecognizeSelector:(SEL)aSelector,抛出异常表明对象无法识别该消息。若返回了有效的 NSMethodSignature,则会接着调用 - (void)forwardInvocation:(NSInvocation *)anInvocation。在这个方法中,可以修改 NSInvocation 对象,指定新的目标对象来处理该消息,然后调用 [anInvocation invoke] 来执行消息。例如:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(someMethod)) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = anInvocation.selector;
    if ([someOtherObject respondsToSelector:sel]) {
        [anInvocation setTarget:someOtherObject];
        [anInvocation invoke];
    } else {
        [super forwardInvocation:anInvocation];
    }
}

整个消息转发机制为 Objective - C 提供了强大的灵活性,允许在运行时动态处理未识别的消息。