做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的應用】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!