做IOS的同伙都曉得或據說runtime,這個器械很像java的反射機制,但功效遠勝於java的反射。經由過程runtime我們可以靜態的向一個類中添加屬性、成員變量、辦法,和對其停止讀寫拜訪。
1、runtime簡介
RunTime簡稱運轉時。OC就是運轉機會制,也就是在運轉時刻 的一些機制,個中最重要的是新聞機制。
關於C說話,函數的挪用在編譯的時刻會決議挪用哪一個函數。
關於OC的函數,屬於靜態挪用進程,在編譯的時刻其實不能決議真正挪用哪一個函數,只要在真正運轉的時刻才會依據函數的稱號
找到對應的函數來挪用。
現實證實:
在編譯階段,OC可以挪用任何函數,即便這個函數並未完成,只需聲明過就不會報錯。
在編譯階段,C說話挪用未完成的函數就會報錯。
2、runtime感化
1.發送新聞
辦法挪用的實質,就是讓對象發送新聞。
objc_msgSend,只要對象能力發送新聞,是以以objc開首.
應用新聞機制條件,必需導入#import <objc/message.h>
新聞機制簡略應用
新聞機制道理:對象依據辦法編號SEL去映照表查找對應的辦法完成
// 創立person對象 Person *p = [[Person alloc] init]; // 挪用對象辦法 [p eat]; // SEL:辦法編號,依據辦法編號便可以找到對應辦法完成 [p performSelector:@selector(eat)]; // 實質:讓對象發送新聞 objc_msgSend(p, @selector(eat)); // 挪用類辦法的方法:兩種 // 第一種經由過程類名挪用實質類名轉換成類對象 [Person eat]; // 第二種經由過程類對象挪用 [[Person class] eat]; [personClass performSelector:@selector(eat)]; // 用類名挪用類辦法,底層會主動把類名轉換成類對象挪用 // 實質:讓類對象發送新聞 objc_msgSend([Person class], @selector(eat));
2.交流辦法
開辟應用場景:體系自帶的辦法功效不敷,給體系自帶的辦法擴大一些功效,而且堅持原本的功效。
方法一:繼續體系的類,重寫辦法.
方法二:應用runtime,交流辦法.
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 需求:給imageNamed辦法供給功效,每次加載圖片就斷定下圖片能否加載勝利。
// 步調一:先弄個分類,界說一個能加載圖片而且能打印的辦法+ (UIImage *)xmg_imageNamed:(NSString *)imageName;
// 步調二:交流imageNamed和xmg_imageNamed的完成,就可以挪用xmg_imageNamed,直接挪用xmg_imageNamed的完成。
UIImage *image = [UIImage imageNamed:@"123"];
imageNamed:
完成辦法:底層挪用PH_imageNamed
實質:交流兩個辦法的完成imageNamed和PH_imageNamed辦法
挪用imageNamed其實就是挪用PH_imageNamed
imageNamed加載圖片,其實不曉得圖片能否加載勝利
今後挪用imageNamed的時刻,就曉得圖片能否加載
}
@end
@implementation UIImage (Image)
// 加載分類到內存的時刻挪用
+ (void)load
{
// 交流辦法完成,辦法都是界說在類外面
// class_getMethodImplementation:獲得辦法完成
// class_getInstanceMethod:獲得對象
// class_getClassMethod:獲得類辦法
// IMP:辦法完成
// imageNamed
// Class:獲得哪一個類辦法
// SEL:獲得辦法編號,依據SEL就可以去對應的類找辦法
Method imageNameMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
Method PH_imageNameMethod = class_getClassMethod([UIImage class], @selector(PH_imageNamed:));
// 交流辦法完成
method_exchangeImplementations(imageNameMethod, PH_imageNameMethod);
}
}
// 不克不及在分類中重寫體系辦法imageNamed,由於會把體系的功效給籠罩失落,並且分類中不克不及挪用super.
// 既能加載圖片又能打印
+ (UIImage *)PH_imageNamed:(NSString *)imageName
{
// 加載圖片
UIImage *image = [UIImage PH_imageNamed:imageName];
// 2.斷定功效
if (image == nil) {
NSLog(@"加載為空");
}
return image;
}
@end
3.靜態添加辦法
開辟應用場景:假如一個類辦法異常多,加載類到內存的時刻也比擬消耗資本,須要給每一個辦法生成映照表,可使用靜態給某個類,添加辦法處理。
簡略應用
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Person *p = [[Person alloc] init];
// 默許person,沒有完成eat辦法,可以經由過程performSelector挪用,然則會報錯。
// 靜態添加辦法就不會報錯
[p performSelector:@selector(eat)];
}
@end
@implementation Person
// void(*)()
// 默許辦法都有兩個隱式參數,
默許一個辦法都有兩個參數,self,_cmd,隱式參數
self:辦法挪用者
_cmd:挪用辦法的編號
void eat(id self,SEL sel)
{
NSLog(@"%@ %@",self,NSStringFromSelector(sel));
}
// 當一個對象挪用未完成的辦法,會挪用這個辦法處置,而且會把對應的辦法列表傳過去.
// 恰好可以用來斷定,未完成的辦法是否是我們想要靜態添加的辦法
<!--靜態添加辦法,起首完成這個resolveInstanceMethod-->
<!-- resolveInstanceMethod挪用:當挪用了沒有完成的辦法沒有完成就會挪用resolveInstanceMethod-->
<!-- resolveInstanceMethod感化:就曉得哪些辦法沒有完成,從而靜態添加辦法-->
<!-- sel:沒有完成辦法-->
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == @selector(eat)) {
// 靜態添加eat辦法
// 第一個參數:給哪一個類添加辦法
// 第二個參數:添加辦法的辦法編號
// 第三個參數:添加辦法的函數完成(函數地址)
// 第四個參數:函數的類型,(前往值+參數類型) v:void @:對象->self :表現SEL->_cmd
class_addMethod(self, @selector(eat), eat, "v@:");
}
return [super resolveInstanceMethod:sel];
}
@end
4.給分類添加屬性
道理:給一個類聲明屬性,其實實質就是給這個類添加聯系關系,其實不是直接把這個值的內存空間添加到類存空間。
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 給體系NSObject類靜態添加屬性name
NSObject *objc = [[NSObject alloc] init];
objc.name = @"abc";
NSLog(@"%@",objc.name);
}
@end
// 界說聯系關系的key
static const char *key = "name";
- (void)setName:(NSString *)name
{
// 添加屬性,跟對象
// 給某個對象發生聯系關系,添加屬性
// object:給哪一個對象添加屬性
// key:屬性名,依據key去獲得聯系關系的對象 ,void * == id
// value:聯系關系的值
// policy:戰略
objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name
{
return objc_getAssociatedObject(self, @"name");
}
以上就是IOS中runtime的應用總結,本篇文章重要是道理和用法總結,runtime的功效很壯大,還須要同伙們多多進修和研討才可以。願望本文對年夜家有所贊助。
【總結iOS中runtime的應用】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!