MST

星途 面试题库

面试题:Objective-C 类的动态特性与方法解析

Objective-C 具有动态特性,当向一个对象发送一个它并不直接实现的消息时,系统会进行方法解析。请描述这个过程,包括动态方法解析、备用接收者和完整的消息转发流程,并且举例说明在实际开发中这种机制的应用场景。
22.7万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

方法解析过程

  1. 动态方法解析: 当向一个对象发送它不直接实现的消息时,首先进入动态方法解析阶段。运行时系统会调用 + (BOOL)resolveInstanceMethod:(SEL)sel(对于实例方法) 或 + (BOOL)resolveClassMethod:(SEL)sel(对于类方法)。在这个方法中,类可以动态添加方法实现。例如:
#import <objc/runtime.h>

@interface MyClass : NSObject
@end

@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(missingMethod)) {
        class_addMethod(self, sel, (IMP)customMethodImplementation, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void customMethodImplementation(id self, SEL _cmd) {
    NSLog(@"This is a dynamically added method.");
}
@end
  1. 备用接收者: 如果动态方法解析没有处理消息,运行时会尝试寻找备用接收者。它会调用 -(id)forwardingTargetForSelector:(SEL)aSelector。在这个方法中,可以返回能够响应这个消息的其他对象。例如:
@interface MyClass : NSObject
@end

@interface AnotherClass : NSObject
- (void)handleMessage;
@end

@implementation AnotherClass
- (void)handleMessage {
    NSLog(@"AnotherClass handled the message.");
}
@end

@implementation MyClass
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(handleMessage)) {
        return [[AnotherClass alloc] init];
    }
    return nil;
}
@end
  1. 完整的消息转发流程: 如果备用接收者也没有找到合适的处理对象,进入完整的消息转发流程。首先会调用 -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector,在这里需要返回一个 NSMethodSignature 对象来描述方法的参数和返回值类型。如果返回 nil,则会调用 -(void)doesNotRecognizeSelector:(SEL)aSelector 抛出异常。若成功返回 NSMethodSignature,则会调用 -(void)forwardInvocation:(NSInvocation *)anInvocation,在这个方法中可以手动转发消息到其他对象或进行自定义处理。例如:
@interface MyClass : NSObject
@end

@interface AnotherClass : NSObject
- (void)handleMessageWithArg:(NSString *)arg;
@end

@implementation AnotherClass
- (void)handleMessageWithArg:(NSString *)arg {
    NSLog(@"AnotherClass handled the message with arg: %@", arg);
}
@end

@implementation MyClass
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(handleMessageWithArg:)) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    AnotherClass *obj = [[AnotherClass alloc] init];
    if ([obj respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:obj];
    }
}
@end

实际开发应用场景

  1. 代理模式简化:通过消息转发机制,可以在不需要显式实现代理方法的情况下,将消息转发给合适的代理对象,简化代码结构。
  2. 动态添加功能:在运行时根据需要动态添加方法实现,例如实现一些特定条件下才需要的功能,减少初始代码体积。
  3. 模拟多继承:虽然 Objective - C 不支持多继承,但通过消息转发可以将消息转发给多个不同的对象,模拟类似多继承的效果。