總結iOS中runtime的使用_IOS

來源:互聯網
上載者:User

做iOS的朋友都知道或聽說runtime,這個東西很像java的反射機制,但功能遠勝於java的反射。通過runtime我們可以動態向一個類中添加屬性、成員變數、方法,以及對其進行讀寫訪問。

一、runtime簡介

RunTime簡稱運行時。OC就是運行時機制,也就是在運行時候 的一些機制,其中最主要的是訊息機制。

對於C語言,函數的調用在編譯的時候會決定調用哪個函數

對於OC的函數,屬於動態調用過程,在編譯的時候並不能決定真正調用哪個函數,只有在真正啟動並執行時候才會根據函數的名稱

找到對應的函數來調用。

事實證明:

    在編譯階段,OC可以調用任何函數,即使這個函數並未實現,只要聲明過就不會報錯。

    在編譯階段,C語言調用未實現的函數就會報錯。

二、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// 定義關聯的keystatic 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的功能很強大,還需要朋友們多多學習和研究才可以。希望本文對大家有所協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.