iOS中runtime機制的理解與簡單使用

1.對runtime的理解

  • runtime是系統(tǒng)在運行的時候的一些機制,其中最主要的是消息機制。
  • OC從三種不同的層級上與runtime進(jìn)行交互,分別是通過OC源碼,通過Foundation框架的NSObject類定義的方法,通過對runtime函數(shù)的直接調(diào)用。大部分情下runtime自動在幕后工作。
  • 對于C語言,函數(shù)的調(diào)用在編譯的時候會決定調(diào)用哪個函數(shù),編譯完成之后直接順序執(zhí)行,無任何二義性。
  • OC的函數(shù)調(diào)用成為消息發(fā)送。屬于動態(tài)調(diào)用過程。在編譯的時候并不能決定真正調(diào)用哪個函數(shù)(事實證明,在編譯階段,OC可以調(diào)用任何函數(shù),即使這個函數(shù)并未實現(xiàn),只要申明過就不會報錯。而C語言在編譯階段就會報錯)。

2. runtime的使用

  • 1.將某些OC代碼轉(zhuǎn)為運行時代碼,探究底層。
  • 2.攔截系統(tǒng)自帶的方法調(diào)用,也可以說成對系統(tǒng)的方法進(jìn)行替換,比如攔截imageNamed:、viewDidLoad、alloc;例如:
    • a、為UIImage建一個分類(UIImage+Category),實現(xiàn)一個自定義方法
+ (UIImage *)customImageNamed:(NSString *)name {
                  doubleversion = [[UIDevicecurrentDevice].systemVersiondoubleValue];
                      if(version >=8.0) {
                             // 如果系統(tǒng)版本是8.0以上,使用另外一套文件名結(jié)尾是‘_os7’的扁平化圖片
                             name = [name stringByAppendingString:@"_os7"];   
                       }
               return[UIImagecustomNamed:name];
}
    - b、分類中重寫UIImage的load方法,實現(xiàn)方法的交換
+ (void) load {
                // 獲取兩個類的類方法
                Method m1 = class_getClassMethod([UIImageClass],@selector(imageNamed:));
                Method m2 = class_getClassMethod([UIImageClass],@selector(customImageNamed:));
                method_exchangeImplementations(m1, m2);
}
  >注意:自定義方法中最后一定要再調(diào)用一下系統(tǒng)的方法,讓其有加載圖片的功能,但是由于方法交換,系統(tǒng)的方法名已經(jīng)變成了我們自定義的方法名(有點繞,就是用我們的名字能調(diào)用系統(tǒng)的方法,用系統(tǒng)的名字能調(diào)用我們的方法),這就實現(xiàn)了系統(tǒng)方法的攔截!
  • 3.實現(xiàn)分類也可以增加屬性。
  • 4.實現(xiàn)NSCoding的自動歸檔和自動解檔;(不用對每個屬性edcode和decode了,使用運行時可以遍歷出每個對象的屬性,數(shù)組的方式遍歷eccode,decode)
    • 用運行時的歸檔方法
- (void) encodeWithCoder: (NSCoder *) encoder {
              unsigned int count = 0;
              Ivar *ivars = class_copyIvarList([Person class], &count);
              for (int i = 0; i < count; i++) {
                  // 取出i位置對應(yīng)的成員變量
                  Ivar ivar = ivars[i];
                  // 查看成員變量
                  const char *name = ivar_getName(ivar);
                  // 歸檔
                  NSString *key = [NSString stringWithUTF8String:name];
                  id value = [self valueForKey:key];
                  [encoder encodeObject: value forKey:key];
              }
              free(ivars);
}
   -  用運行時的解歸檔方法
- (id) initWithCoder: (NSCoder *) decoder {
              if (self = [super init]) {
                  unsigned int count = 0;
                  Ivar *ivars = class_copyIvarList([Person class], &count);
                  for (int i = 0; i < count; i++) {
                        // 取出i位置對應(yīng)的成員變量
                        Ivar ivar = ivars[i];
                        // 查看成員變量
                        const char *name = ivar_getName(ivar);
                        // 歸檔
                        NSString *key = [NSString stringWithUTF8String:name];
                        id value = [self valueForKey:key];
                        [encoder encodeObject: value forKey:key];
                   }
                  free(ivars);
              }
              return self;
}
  • 5.實現(xiàn)字典和模型的自動轉(zhuǎn)換(核心就是可以遍歷出字典中的每個屬性,json解析中大牛框架都用了這個特性,包括MJEXtension,YYModel,jsonModel都是將json轉(zhuǎn)換為字典,再遍歷字典中的每個屬性來進(jìn)行modle的轉(zhuǎn)換)。
    • 經(jīng)查看源碼發(fā)現(xiàn)獲取屬性的列表的方法是字典轉(zhuǎn)模型的比較核心方法:
      OBJC_EXPORT Ivar *class_copyIvarList(Class cos, unsigned int *outCount)
      __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);

    結(jié)論: 使用運行時動態(tài)獲取屬性的屬性名的方法,來進(jìn)行字典轉(zhuǎn)模型替換,字典轉(zhuǎn)模型效率最高的(耗時最短的)的是KVC,其他的字典轉(zhuǎn)模型是在KVC 的key 和Value 做處理,動態(tài)的獲取json 中的key 和value

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容