美文网首页
运行时runtime一些方法简单描述

运行时runtime一些方法简单描述

作者: 星空梦想 | 来源:发表于2016-12-07 18:30 被阅读20次

    Demo


    demo地址

    class_copyPropertyList返回的仅仅是对象类的属性(@property申明的属性),而class_copyIvarList返回类的所有属性和变量(包括在@interface大括号中声明的变量)

    /*cls:被添加方法的类

    name:可以理解为方法名,这个貌似随便起名,比如我们这里叫guess

    imp:实现这个方法的函数

    types:一个定义该函数返回值类型和参数类型的字符串,这个具体会在后面讲

    class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <nzrm1v#const char *types#>)

    class_addMethod([EmptyClass class], @selector(say:), (IMP)say, "i@:@");

    其中types参数为"i@:@“,按顺序分别表示:

    i:返回值类型int,若是v则表示void

    @:参数id(self)

    ::SEL(_cmd)

    @:id(str)

    +(void)load

    {

          static dispatch_once_t onceToken;

         dispatch_once(&onceToken,^{

             Class selfClass = [self class];

             SEL oriSel = @selector(sendAction:to:forEvent:);

           //        得到类的实例方法 class_getInstanceMethod

           Method oriMethod = class_getInstanceMethod(selfClass, oriSel);

           SEL cusSel = @selector(mySendAction:to:forEvent:);

          Method cusMethod = class_getInstanceMethod(selfClass, cusSel);

         //        每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP有点类似函数指针,指向具体的Method实现。

        //        我们可以利用 method_exchangeImplementations 来交换2个方法中的IMP,//        我们可以利用 class_replaceMethod 来修改类,

       //        我们可以利用 method_setImplementation 来直接设置某个方法的IMP,

       //        ……

       //

       //        归根结底,都是偷换了selector的IMP

         IMP cusImp = method_getImplementation(cusMethod);

        BOOL addsucc = class_addMethod(selfClass, oriSel, cusImp,    method_getTypeEncoding(cusMethod));

      if (addsucc) {

              IMP oriImp = method_getImplementation(oriMethod);

             class_replaceMethod(selfClass, cusSel, oriImp, method_getTypeEncoding(oriMethod));

         }else{

             method_exchangeImplementations(oriMethod, cusMethod);

    }

    });


    NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];

    //2.3 成员属性名 => 字典key

    NSString *key = [ivarName substringFromIndex:1];

    //2.4 去字典中取出对应value给模型属性赋值

    id value = dict[key];

    //获取成员属性类型

    NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];

    //二级转换,字典中还有字典,也需要把对应字典转换成模型

    //判断下value,是不是字典

    if([value isKindOfClass:[NSDictionary class]]&& ![ivarType containsString:@"NS"]){//是字典对象。并且属性名对应类型是自定义类型

    //user User

    //处理类型字符串 @\"User\" -> User

    ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];

    ivarType = [ivarType stringByReplacingOccurrencesOfString:@"\"" withString:@""];

    //自定义对象,并且值是字典

    //value:user字典 ->User模型

    //获取模型(user)类对象

    Class modalClass = NSClassFromString(ivarType);

    //字典转模型

    if (modalClass) {

    //字典转模型

    value = [modalClass objectWithDict:value];

    }

    //字典,user

    NSLog(@"%@",key);

    }

    //三级转换:NSArray中也是字典,把数组中的字典转换成模型

    //判断是否是数组

    if ([value isKindOfClass:[NSArray class]]) {

    //判断对应类有没有实现字典数组转模型数组的协议

    if ([self instancesRespondToSelector:@selector(arrayContainModelClass)]) {

    //转换成id类型,就能调用任何对象的方法

    id idSelf = self;

    //获取数组中字典对应的模型

    NSString *type = [idSelf arrayContainModelClass][key];

    //生成模型

    Class classModel = NSClassFromString(type);

    NSMutableArray *arrM = [NSMutableArray array];

    //遍历字典数组,生成模型数组

    for (NSDictionary *dict in value) {

    //字典转模型

    id model = [classModel objectWithDict:dict];

    [arrM addObject:model];

    }

    //把模型数组赋值给value

    value = arrM;

    }

    }

    //2.5KVC字典转模型

    if (value) {

    [objc setValue:value forKey:key];

    }

    }

    //返回对象

    return objc;

    }

    相关文章

      网友评论

          本文标题:运行时runtime一些方法简单描述

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