方法解析过程
- 动态方法解析:
当向一个对象发送它不直接实现的消息时,首先进入动态方法解析阶段。运行时系统会调用
+ (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
- 备用接收者:
如果动态方法解析没有处理消息,运行时会尝试寻找备用接收者。它会调用
-(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
- 完整的消息转发流程:
如果备用接收者也没有找到合适的处理对象,进入完整的消息转发流程。首先会调用
-(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
实际开发应用场景
- 代理模式简化:通过消息转发机制,可以在不需要显式实现代理方法的情况下,将消息转发给合适的代理对象,简化代码结构。
- 动态添加功能:在运行时根据需要动态添加方法实现,例如实现一些特定条件下才需要的功能,减少初始代码体积。
- 模拟多继承:虽然 Objective - C 不支持多继承,但通过消息转发可以将消息转发给多个不同的对象,模拟类似多继承的效果。