美文网首页
iOS 之runtime消息传递和转发

iOS 之runtime消息传递和转发

作者: 男人宫 | 来源:发表于2022-02-18 14:46 被阅读0次
    runtime 运行时,oc是一门动态性语言,程序在运行时可改变结构,如添加方法,交换方法等.其实runtime就是一组用c语言写的api

    消息转发流程如下:

    先调用实例方法resolveInstanceMethod
    如果在这里使用runtime动态添加对应的方法,并且返回yes。就万事大吉。对象找到了处理的方法,
    并且将这个新增的方法添加到类的方法缓存列表

    如果上面的方法返回NO的话,对象会调用forwardingTargetForSelector方法
    允许作者选择其他的对象,处理这个消息。
    这个方法,也是待会我们要做文章的地方。画重点。

    如果上面两个方法都没有做处理,那么对象会执行最后一个方法methodSignatureForSelector,提供一个有效的方法签名,若提供了有效的方法签名,程序将会通过forwardInvocation方法执行签名。若没有提供方法签名就会触发doesNotRecognizeSelector方法,触发崩溃。

      Person *p = [Person new];
        //调用一个未实现的实例方法
       [p test];
        //调用一个未实现的类方法
        [Person test1];
        //如果调用一个没有实现的方法,且没有动态解析,就会进行消息转发
        [p study];
    -------------------------------------------
    //person类
    #import "Person.h"
    #import <objc/runtime.h>
    #import "Man.h"
    @implementation Person
    
    //调用实例方法时未实现的话就会用此方法进行动态解析
    +(BOOL)resolveInstanceMethod:(SEL)sel
    {
        //runtime动态添加方法
        //v是返回值为void @:为固定格式  后面如果要参数跟对应的参数类型
        class_addMethod(self.class, sel, class_getMethodImplementation(self.class, @selector(newMethods)), "v@:");
        return  YES;
    }
    - (void)newMethods
    {
        NSLog(@"我是动态添加的方法");
    }
    
    
    //调用类方法时未实现的话就会用此方法进行动态解析
    + (BOOL)resolveClassMethod:(SEL)sel
    {
        //runtime动态添加方法
        //类方法存在元类中 所以要获取元类 给元类添加方法 objc_getMetaClass获取元类 
        class_addMethod(objc_getMetaClass("Person"), sel, class_getMethodImplementation(self.class, @selector(newClassMetods)), "v@:");
        return  YES;
    }
    - (void)newClassMetods
    {
        NSLog(@"我是动态添加的");
    }
    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
        //指定一个对象来响应没有实现的方法
        return [Man new];
    }
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    
    -(void)forwardInvocation:(NSInvocation *)anInvocation
    {
        [anInvocation invokeWithTarget:[Man new]];
    }
    @end
    
    -----------------------------------------------
    //Man类
    #import "Man.h"
    
    @implementation Man
    - (void)study
    {
        NSLog(@"我帮人类响应了这个方法");
    }
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS 之runtime消息传递和转发

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