Runtime看这个好懂,还全

作者: 未来可期me | 来源:发表于2017-03-27 18:20 被阅读100次

    Runtime讲解

    1. Runtime简介

    RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。
    对于C语言,函数的调用在编译的时候会决定调用哪个函数
    对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。
    事实证明:
    在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。
    在编译阶段,C语言调用未实现的函数就会报错。

    2.Runtime作用

    Runtime作用之发送消息

    方法调用的本质,就是让对象发送消息。
    objc_msgSend,只有对象才能发送消息,因此以objc开头.
    使用消息机制前提,必须导入#import <objc/message.h>
    消息机制简单使用
    消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现

    • 简单举个例子
    发送消息.png

    runtime作用之交换方法

    开发使用场景:系统自带的方法功能不够,给系统自带的方法扩展一些功能,并且保持原有的功能。
    方式一:继承系统的类,重写方法.
    方式二:使用runtime,交换方法.
    方式三:使用分类category


    下面是对交换方法的使用---runtime修改系统viewWillAppear方法


    无标题.png
    • 先看图,下面解释为啥这么写???
    无标题.png
    • 注意看这个断点,是不是,没走系统方法,交换了吧-----
    无标题.png
    • 下面把代码贴一下,方便自己与大家copy
      //由于交换方法我们希望在工程运行期间只执行一次,所以通常写在load里面
    + (void)load {
        Class class = [self class];
        
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(dgviewWillAppear:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    
    }
    

    简写

    + (void)load {  
        Method imageMethodNamed = class_getClassMethod(self, @selector(imageNamed:));  
        Method myImageMethodNamed = class_getClassMethod(self, @selector(myImageNamed:));  
        //实现两个方法的交换  
        method_exchangeImplementations(myImageMethodNamed,imageMethodNamed);  
    } 
    
    

    3runtime作用之动态添加方法

    开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。
    经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法

    无标题.png

    动态方法实现eat,Person.h是不用申明eat方法的,但是如果Person.m中不实现这个方法,编译通过,执行报错unrecognized selector sent to instance


    performSelector调用和直接调用的区别

    前者执行的方法是不需要在.h中声明的,编译过程绝对通过,但是如果调用该方法的类中没有实
    现该方法,执行过程中会出现crash
    后者直接调用,所调用的方法在.h中必须声明,否则编译都不能通过,并且与上面方法一样,
    如果执行过程中发现没有实现该方法,执行过程中会出现crash
    
    

    4Runtime之属性绑定


    就是将数据绑定到手势对象上,然后在点击的时候,从手势对象上取数据

    for (int i = 0; i < _roomInfo.rec_goods.count; i++) {
                RoomRecgoodInfo *recgoodInfo = _roomInfo.rec_goods[i];
                UIImageView *hotGoodImage = [[UIImageView alloc] initWithFrame:CGRectMake(i*(hotGoodImageH+12), 0, hotGoodImageH, hotGoodImageH)];
                hotGoodImage.layer.masksToBounds = YES;
                hotGoodImage.layer.cornerRadius = 5;
                hotGoodImage.userInteractionEnabled = YES;
                [hotGoodImage sd_setImageWithURL:[NSURL URLWithString:recgoodInfo.cover] placeholderImage:GOODSDEFAULTImge];
                
                UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapHotGoods:)];
                [hotGoodImage addGestureRecognizer:tap];
                [scroller addSubview:hotGoodImage];
                
                //runtime将数据绑定到该view之上
                objc_setAssociatedObject(tap, @"recgoodInfo", recgoodInfo, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
                
                UILabel *priceLab = [[UILabel alloc] initWithFrame:CGRectMake(X(hotGoodImage), MaxY(hotGoodImage), WIDTH(hotGoodImage), 35)];
                priceLab.textColor = [UIColor colorWithHexString:@"#FF0707"];
                priceLab.textAlignment = NSTextAlignmentCenter;
                priceLab.font = [UIFont systemFontOfSize:16];
                priceLab.text = [NSString stringWithFormat:@"¥%@",recgoodInfo.price];
                [scroller addSubview:priceLab];
    
            }
    
    
    
    //点击热销商品,去往商品详情
    - (void)tapHotGoods:(UITapGestureRecognizer *)tap {
        RoomRecgoodInfo *recgoodInfo = objc_getAssociatedObject(tap, @"recgoodInfo");
        GoodsDetailController *vc = [GoodsDetailController new];
        vc.goodsId = recgoodInfo.goods_id;
        vc.isPublishGoodsVC = YES;
        
        //创建直播小窗口
        [self createLiveWindow];
        
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
        [self presentViewController:nav animated:YES completion:nil];
    
        
    }
    

    5Runtime实现模型转换

    1. 字典转模型介绍
      现在的ios开发中,我们通常会使用MVC模式。当我们拿到数据的时候,我们要把数据转成模型使用。
      2.字典转模型的好处:
      (1)降低代码的耦合度
      (2)所有字典转模型部分的代码统一集中在一处处理,降低代码出错的几率
      (3)在程序中直接使用模型的属性操作,提高编码效率
      (4)调用方不用关心模型内部的任何处理细节
    1. 利用runtime实现转换:
      通过动态获取属性列表,然后取出属性,由属性在数据字典获取值,然后在赋值给该模型属性。当对象的属性很少的时候,直接字典取出对应属性值简单赋值即可。
    无标题.png 无标题.png 无标题.png ![无标题.png](http:https://img.haomeiwen.com/i1398395/88e64d369492e0cf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![无标题.png](http:https://img.haomeiwen.com/i1398395/103f9fb266f54677.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    以上是有问题的例子


    无标题.png

    这就对了吧,不怕模型转换的时候出现key对不上,导致的问题了吧。

    以上就是常用的一些runtime概念,其实平时我们不太会用这个。毕竟现在用这个的东西都有现成的三方库。。。。不过还是了解一下好,这个代码的世界还是很神奇的不是!!停笔!!!

    相关文章

      网友评论

        本文标题:Runtime看这个好懂,还全

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