蘋果不推薦我們使用runtime恼除, 因此runtime是沒有提示的掏湾。
打開提示將如下參數(shù)設(shè)置為no
我們通過2種調(diào)用類的實(shí)例方法的過程來研究
一下OC代碼是如何轉(zhuǎn)換成runtime代碼的
@interface SWPerson : NSObject
- (void )eat;
@end
@implementation SWPerson
- (void )eat
{
NSLog(@"吃飯");
}
@end
OC代碼
SWPerson *p = [[SWPerson alloc]init];
[p eat];
runtime代碼
id p = objc_msgSend(objc_getClass("SWPerson"), sel_registerName("alloc"));
objc_msgSend(p, sel_registerName("init"));
objc_msgSend(p, sel_registerName("eat"));
OC代碼實(shí)際上都會被編譯器轉(zhuǎn)換成 runtime代碼執(zhí)行。
runtime應(yīng)用一 修改系統(tǒng)方法的實(shí)現(xiàn)
下面的方法將 imageNamed: 改成 imageWithNamed:執(zhí)行当船。
這樣可以做到監(jiān)聽系統(tǒng)的方法要糊,然后在需要的時(shí)候 執(zhí)行。
.h文件
#import <UIKit/UIKit.h>
@interface UIImage (exchange)
+ (UIImage *)imageWithNamed:(NSString *)name;
@end
.m文件
#import "UIImage+exchange.h"
#import <objc/message.h>
@implementation UIImage (exchange)
+(void)load{
Method systemMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
Method custormMethod = class_getClassMethod([UIImage class], @selector(imageWithNamed:));
method_exchangeImplementations(systemMethod, custormMethod);
}
+ (UIImage *)imageWithNamed:(NSString *)name{
UIImage *image = [UIImage imageWithNamed:name];
if (image == nil) {
NSLog(@"%@圖片加載失敗",name);
}
return image;
}
@end
原理解析
1 image對象找到該方法對應(yīng)的編號;
2 通過方法的編號,找到方法列表中對應(yīng)的方法
3 通過找到了方法列表中對應(yīng)的方法,找到對應(yīng)的方法的實(shí)現(xiàn)
4 在以上三點(diǎn)方法開始之前,我們通過load方法在OC的底層實(shí)現(xiàn)了對兩個方法實(shí)現(xiàn)的交換
5 當(dāng)外面用對象調(diào)用(imageNamed:)的方法的時(shí)候其實(shí)由于交換的方法實(shí)現(xiàn)的原因,該對象會去找(imageWithNamed:)方法的實(shí)現(xiàn),當(dāng)程序進(jìn)入了(imageWithNamed:)方法的時(shí)候,在運(yùn)行第二個(imageWithNamed:)方法的時(shí)候,其實(shí)是調(diào)用(imageNamed:)方法,然后再進(jìn)行判斷,如果輸入的不是圖片,那么自然的顯示,加載失敗.這就是runtime的交換方法.