Runtime讲解
1. Runtime简介
RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。
对于C语言,函数的调用在编译的时候会决定调用哪个函数
对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。
事实证明:
在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。
在编译阶段,C语言调用未实现的函数就会报错。
2.Runtime作用
Runtime作用之发送消息
方法调用的本质,就是让对象发送消息。
objc_msgSend,只有对象才能发送消息,因此以objc开头.
使用消息机制前提,必须导入#import <objc/message.h>
消息机制简单使用
消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现
- 简单举个例子
runtime作用之交换方法
开发使用场景:系统自带的方法功能不够,给系统自带的方法扩展一些功能,并且保持原有的功能。
方式一:继承系统的类,重写方法.
方式二:使用runtime,交换方法.
方式三:使用分类category
下面是对交换方法的使用---runtime修改系统viewWillAppear方法
无标题.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作用之动态添加方法
无标题.png开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。
经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法
动态方法实现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实现模型转换
- 字典转模型介绍
现在的ios开发中,我们通常会使用MVC模式。当我们拿到数据的时候,我们要把数据转成模型使用。
2.字典转模型的好处:
(1)降低代码的耦合度
(2)所有字典转模型部分的代码统一集中在一处处理,降低代码出错的几率
(3)在程序中直接使用模型的属性操作,提高编码效率
(4)调用方不用关心模型内部的任何处理细节
- 利用runtime实现转换:
通过动态获取属性列表,然后取出属性,由属性在数据字典获取值,然后在赋值给该模型属性。当对象的属性很少的时候,直接字典取出对应属性值简单赋值即可。
以上是有问题的例子
无标题.png
这就对了吧,不怕模型转换的时候出现key对不上,导致的问题了吧。
以上就是常用的一些runtime概念,其实平时我们不太会用这个。毕竟现在用这个的东西都有现成的三方库。。。。不过还是了解一下好,这个代码的世界还是很神奇的不是!!停笔!!!
网友评论