Runtime講解
1. Runtime簡介
RunTime簡稱運行時。OC就是運行時機制,也就是在運行時候的一些機制,其中最主要的是消息機制。
對于C語言,函數(shù)的調(diào)用在編譯的時候會決定調(diào)用哪個函數(shù)
對于OC的函數(shù),屬于動態(tài)調(diào)用過程,在編譯的時候并不能決定真正調(diào)用哪個函數(shù),只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)來調(diào)用。
事實證明:
在編譯階段,OC可以調(diào)用任何函數(shù),即使這個函數(shù)并未實現(xiàn),只要聲明過就不會報錯。
在編譯階段,C語言調(diào)用未實現(xiàn)的函數(shù)就會報錯。
2.Runtime作用
Runtime作用之發(fā)送消息
方法調(diào)用的本質(zhì),就是讓對象發(fā)送消息。
objc_msgSend,只有對象才能發(fā)送消息,因此以objc開頭.
使用消息機制前提,必須導入#import <objc/message.h>
消息機制簡單使用
消息機制原理:對象根據(jù)方法編號SEL去映射表查找對應的方法實現(xiàn)
- 簡單舉個例子
runtime作用之交換方法
開發(fā)使用場景:系統(tǒng)自帶的方法功能不夠,給系統(tǒng)自帶的方法擴展一些功能,并且保持原有的功能。
方式一:繼承系統(tǒng)的類,重寫方法.
方式二:使用runtime,交換方法.
方式三:使用分類category
下面是對交換方法的使用---runtime修改系統(tǒng)viewWillAppear方法
- 先看圖,下面解釋為啥這么寫???
- 注意看這個斷點,是不是,沒走系統(tǒng)方法,交換了吧-----
- 下面把代碼貼一下,方便自己與大家copy
//由于交換方法我們希望在工程運行期間只執(zhí)行一次,所以通常寫在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:));
//實現(xiàn)兩個方法的交換
method_exchangeImplementations(myImageMethodNamed,imageMethodNamed);
}
3runtime作用之動態(tài)添加方法
開發(fā)使用場景:如果一個類方法非常多,加載類到內(nèi)存的時候也比較耗費資源,需要給每個方法生成映射表,可以使用動態(tài)給某個類,添加方法解決。
經(jīng)典面試題:有沒有使用performSelector,其實主要想問你有沒有動態(tài)添加過方法
動態(tài)方法實現(xiàn)eat,Person.h是不用申明eat方法的,但是如果Person.m中不實現(xiàn)這個方法,編譯通過,執(zhí)行報錯unrecognized selector sent to instance
performSelector調(diào)用和直接調(diào)用的區(qū)別
前者執(zhí)行的方法是不需要在.h中聲明的,編譯過程絕對通過,但是如果調(diào)用該方法的類中沒有實
現(xiàn)該方法,執(zhí)行過程中會出現(xiàn)crash
后者直接調(diào)用,所調(diào)用的方法在.h中必須聲明,否則編譯都不能通過,并且與上面方法一樣,
如果執(zhí)行過程中發(fā)現(xiàn)沒有實現(xiàn)該方法,執(zhí)行過程中會出現(xiàn)crash
4Runtime之屬性綁定
就是將數(shù)據(jù)綁定到手勢對象上,然后在點擊的時候,從手勢對象上取數(shù)據(jù)
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將數(shù)據(jù)綁定到該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;
//創(chuàng)建直播小窗口
[self createLiveWindow];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];
}
5Runtime實現(xiàn)模型轉(zhuǎn)換
- 字典轉(zhuǎn)模型介紹
現(xiàn)在的ios開發(fā)中,我們通常會使用MVC模式。當我們拿到數(shù)據(jù)的時候,我們要把數(shù)據(jù)轉(zhuǎn)成模型使用。
2.字典轉(zhuǎn)模型的好處:
(1)降低代碼的耦合度
(2)所有字典轉(zhuǎn)模型部分的代碼統(tǒng)一集中在一處處理,降低代碼出錯的幾率
(3)在程序中直接使用模型的屬性操作,提高編碼效率
(4)調(diào)用方不用關(guān)心模型內(nèi)部的任何處理細節(jié)
- 利用runtime實現(xiàn)轉(zhuǎn)換:
通過動態(tài)獲取屬性列表,然后取出屬性,由屬性在數(shù)據(jù)字典獲取值,然后在賦值給該模型屬性。當對象的屬性很少的時候,直接字典取出對應屬性值簡單賦值即可。
以上是有問題的例子
這就對了吧,不怕模型轉(zhuǎn)換的時候出現(xiàn)key對不上,導致的問題了吧。
以上就是常用的一些runtime概念,其實平時我們不太會用這個。畢竟現(xiàn)在用這個的東西都有現(xiàn)成的三方庫。。。。不過還是了解一下好,這個代碼的世界還是很神奇的不是!!停筆!!!