你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 總結iOS中runtime的應用

總結iOS中runtime的應用

編輯:IOS開發綜合

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

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved