美文网首页
IOS Rutime学习

IOS Rutime学习

作者: copy_farmer | 来源:发表于2022-01-11 21:41 被阅读0次

    1.什么是Runtime

    Runtime是Object-C中的一个库,主要用C和汇编写的,OC编写的代码最终都会转换为Runtime的C代码,用于消息的转发和传递

    2.Runtime的基本用法

    2.1 常用方法介绍
    2.1.1 class_getClassMethod 获取某个类的方法

    Method personMethod  =  class_getClassMethod([Class class], oriSEL);
    

    2.1.2 class_getInstanceMethod 获取某个类的实例方法

    Method changeMethod1 =  class_getInstanceMethod([self class], @selector(changeFunc1));
    Method changeMethod2 =  class_getInstanceMethod([self class], @selector(changeFunc2));
    
    -(void)changeFunc1{
        NSLog(@"========== fuction1 ");
    }
    -(void)changeFunc2{
        NSLog(@"========== fuction2 ");
    }
    

    2.1.3 method_exchangeImplementations 交换两个方法

    method_exchangeImplementations(changeMethod2, changeMethod1);
    

    2.1.4 class_addMethod 添加方法
    我们先定义个Class 叫PersonClass
    第一个参数是添加对象类
    第二个参数是添加的方法
    第三个参数是添加方法的IMP 用class_getMethodImplementation来获取
    第四个参数是 传入方法是什么返回,是否带参 "v@:"等同于返回为void 不带参数

    PersonClass *person = [[PersonClass alloc]init];
    BOOL isAddSuccess =  class_addMethod([person class], @selector(addClass), class_getMethodImplementation([self class], @selector(addClass)), "v@:");
        if(isAddSuccess){
            [person performSelector:@selector(addClass)];
        }
    

    2.1.4 class_replaceMethod替换方法
    第一个参数是替换对象类
    第二个参数是替换的方法
    第三个参数是替换方法的IMP 用class_getMethodImplementation来获取
    第四个参数是 传入方法是什么返回,是否带参 "v@:"等同于返回为void 不带参数

    PersonClass *person = [[PersonClass alloc]init];
     BOOL replaceMethod = class_replaceMethod([person class], @selector(getName), class_getMethodImplementation([self class],@selector(changeClass)),"v@:");
        if(replaceMethod){
            [person performSelector:@selector(getName) withObject:nil];
        }
    

    2.1.5 objc_setAssociatedObject objc_getAssociatedObject属性关联

    OBJC_EXPORT void
    objc_setAssociatedObject
    (
    id _Nonnull object,//被关联对象
    const void * _Nonnull key,//关联的key
     id _Nullable value,//关联的值,属性名
    objc_AssociationPolicy policy//策略一般使用OBJC_ASSOCIATION_RETAIN_NONATOMIC
    )
    
    static char *overviewKey;
    NSArray *array = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
    NSString *arrayDesc = @"this is arrayDesc";
        //关联
    objc_setAssociatedObject(array, &overviewKey, arrayDesc, OBJC_ASSOCIATION_RETAIN);
     NSString *associatedDesc = (NSString *)objc_getAssociatedObject(array, &overviewKey); NSLog(@"associatedDesc:%@", associatedDesc);
     //取消关联
    objc_setAssociatedObject(array, &overviewKey, nil, OBJC_ASSOCIATION_RETAIN);
    NSString *associatedDesc2 = (NSString *)objc_getAssociatedObject(array, &overviewKey);
     NSLog(@"associatedDesc2:%@", associatedDesc2);
    

    2.1.6获取类属性

     PersonClass *person = [[PersonClass alloc]init];
        unsigned int count;
        //获取类属性列表
        objc_property_t *propertyList = class_copyPropertyList([person class], &count);
        for(int i=0;i<count;i++){
            objc_property_t property = propertyList[i];
            NSLog(@"property name=%@",[NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding]);
        }
        
        free(propertyList);
        //获取类方法列表
        Method *methodList = class_copyMethodList([person class],  &count);
        for(int i=0;i<count;i++){
             Method method =  methodList[i];
            NSString *str =  NSStringFromSelector(method_getName(method));
            NSLog(@"method name=%@",str);
        }
        free(methodList);
        //获取成员变量
        Ivar *ivarList = class_copyIvarList([person class],  &count);
        for(int i=0;i<count;i++){
            Ivar ivar = ivarList[i];
            NSString *str = [NSString stringWithUTF8String:ivar_getName(ivar)];
            NSLog(@"ivar name=%@",str);
        }
        free(ivarList);
    

    3 Runtime 消息转发

    在runtime 中 我们用objc_msgSend来传递消息,但是在父类和子类都找不到对应的方法时,runtime会执行如下机制


    aaaa.jpg

    了解消息转发的原理,我们可以在forwardingTargetForSelector进行捕获 避免Unrecognized Selector的错误

    +(BOOL)resolveClassMethod:(SEL)sel{
        if (sel == @selector(messageTest)) {
            NSLog(@"1======resolveClassMethod");
            return YES;
        }
        return NO;
    }
    +(BOOL)resolveInstanceMethod:(SEL)sel{
        if (sel == @selector(messageTest)) {
            NSLog(@"1======resolveInstanceMethod");
            return YES;
        }
        return NO;
    }
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        if (aSelector == @selector(messageTest)) {
            NSLog(@"2======forwardingTargetForSelector");
         }
         return nil;
    }
    

    相关文章

      网友评论

          本文标题:IOS Rutime学习

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