美文网首页
Objective-C消息转发

Objective-C消息转发

作者: 凤栖林 | 来源:发表于2017-08-30 17:19 被阅读0次

OC中调用方法就是向对象发送消息
下面的代码:

 [self performSelector:@selector(method) withObject:nil];

如果说method方法不存在,就会出现:unrecognized selector sent to instance
从发送消息到崩溃中间经历了什么?
首先分两种情况
1,如果发送的是一个实例方法,会经过三个步骤
第一步:

+ (BOOL)resolveInstanceMethod:(SEL)sel

这个方法是实例方法未实现时自动执行,这个方法里面是让你在当前类里面对未实行的方法做弥补

void dynamicMethodIMP(id sel,SEL _cmdd){
    NSLog(@"resolveInstanceMethod调用成功");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if (sel == @selector(method)) {
//        class_addMethod([self class],sel,(IMP));
        class_addMethod([self class],sel,(IMP)dynamicMethodIMP, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

第二步:
如果第一步resolveInstanceMethod你没做处理,便会来到这一步,如果你处理了第一步,第二步是不会执行的

- (id)forwardingTargetForSelector:(SEL)aSelector{
    if (aSelector == @selector(method)) {
        return [TestClass new];
    }
    return nil;
}
@implementation TestClass
- (void)method{
    NSLog(@"method");
}
@end

这一步是在其他类里面找对应的方法,所以TestClass里面必须要实现method方法,不然同样会崩溃
第三步:
经历过第一步,在本类中找弥补方法,第二步,在其他类中找弥补方法后,如果都没有找到,便会来到第三步

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
    if (!methodSignature) {
        methodSignature = [NSMethodSignature signatureWithObjCTypes:"v@:*"];
    }
    return methodSignature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    testClass *messageForwarding = [testClass new];
    if ([messageForwarding respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:messageForwarding];
    }
}

这一步实现方法的重新签名
2.如果是调用了一个类方法,该类方法没有实现该怎么办
便会调用resolveClassMethod

void dynamicMethodIMP(id sel,SEL _cmdd){
    NSLog(@"resolveInstanceMethod调用成功");
}
@implementation testObject
+ (BOOL)resolveClassMethod:(SEL)sel{
  if (sel == @selector(hehe1)){
       class_addMethod(objc_getMetaClass("testObject"),sel,(IMP)dynamicMethodIMP, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
@end

看里面class_addMethod的第一个参数,是objc_getMetaClass("testObject"),该方法是获取当前类的元类,如果用[self class]是会崩溃的,因为dynamicMethodIMP是一个c方法,它是存在于元类里面的MessageList里面的,当前类找不到该方法,元类的知识可以看我另一篇文章:iOS类和元类关系
如果resolveClassMethod方法没有实现,就会直接崩溃,也就是说它没有实例方法里面的第二步和第三步。
resolveInstanceMethod和methodSignatureForSelector、forwardInvocation只是在实例方法缺失才会执行,类方法缺失不会执行,这点要注意

相关文章

  • iOS理解Objective-C中消息转发机制附Demo

    iOS理解Objective-C中消息转发机制附Demo iOS理解Objective-C中消息转发机制附Demo

  • Objective-C 运行时(Runtime)解析

    Objective-C基于C语言加入了面向对象特性和消息转发,Objective-C 的消息转发需要运行时系统来动...

  • 面试题整理

    Objective-C 中的消息与消息转发 深入理解RunLoop Autorelease

  • 2018-02-01

    《Objective-C runtime系列 1》消息发送及转发机制 Objective-C是基于C,加入了面...

  • Objective-C 消息转发

    一些概念 静态绑定:在编译期就能决定运行时所应调用的函数。代表语言:C、C++等动态绑定:所要调用的函数直到运行期...

  • Objective-C 消息转发

    前文提到(https://www.jianshu.com/p/588d1d8c3ee1),消息动态方法解析时会重载...

  • Objective-C消息转发

    理论 1.消息机制 RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。 对于C语言...

  • Objective-C消息转发

    OC中调用方法就是向对象发送消息下面的代码: 如果说method方法不存在,就会出现:unrecognized s...

  • Objective-C消息转发

    1. performSelector:object performSelector在运行时调用方法,由于编译期间不...

  • Objective-C消息转发

    我们要通过一个小例子来简单、通俗的理解一下什么是消息转发以及如何消息转发,希望看完这篇文章时大家会彻底的明白OC的...

网友评论

      本文标题:Objective-C消息转发

      本文链接:https://www.haomeiwen.com/subject/yikxjxtx.html