Objective-C消息发送机制深入研究

objc_msgSend方法

在OC里面,直到运行时消息才绑定到方法的实现,编译器将以下表达式

[receiver message]

转换为调用objc_msgSende的一个方法

objc_msgSend(receiver, selector, arg1, arg2, ...)

查找方法的顺序

  • 通过isa指针找到对应的class,先从class的方法缓存表里面查找。
  • 如果找不到再去的selector分配表里面查找方法。
  • 如果找不到对应的方法,通过super_class指针找到父类,再从父类的分配表里面查找方法,就这样一直找到NSObject

动态添加方法

可以通过实现 resolveInstanceMethod: 或者 resolveClassMethod: 方法分别为实例方法或者类方法动态添加实现。

void dynamicMethodIMP(id self, SEL _cmd) {
    // implementation ....
}

@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically)) {
          class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
          return YES;
    }
    return [super resolveInstanceMethod:aSEL];
}
@end

如果以上的动态方法也没有添加,不用担心,还有机会动态转发消息。

动态转发消息

举个例子,假设小明不想做家庭作业,而是让他的家长代替他做,我们将这种行为模拟出来

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    Parent *parent = [[Parent alloc] init];
    if ([parent respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:parent];
    } else {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    Parent *parent = [[Parent alloc] init];
    if (aSelector == @selector(doSomeHomeWork)) {
        return [parent methodSignatureForSelector:aSelector];
    }
    return nil;
}

Updated:

Comments