前言
objective-c runtime是乙個實現objective-c語言的c庫。它是一門編譯型語言、也是一門動態型的語言(這裡強調下oc是靜態型別語言),之前沒接觸runtime的時候也不覺著它有多重要,接觸之後才發現其實runtime挺強大的。就拿我們在ios開發中所使用的oc程式語言來講,oc之所以能夠做到即是編譯型語言,又能做到動態語言,就是得益於runtime的機制。
最近公司專案中用了一些 runtime 相關的知識, 初看時有些蒙, 雖然用的並不多, 但還是想著系統的把 runtime 相關的常用方法整理一下, 自己以後用著方便, 也希望對看到的朋友有所幫助.
一、runtime 簡介
runtime 簡稱執行時,是系統在執行的時候的一些機制,其中最主程式設計客棧要的是訊息機制。它是一套比較底層的純 c 語言 api, 屬於乙個 c 語言庫,包含了很多底層的 c 語言 api。我們平時編寫的 oc **,在程式執行過程時,其實最終都是轉成了 runtime 的 c 語言**。如下所示:
// oc**:
[person coding];
//執行時 runtime 會將它轉化成 c 語言的**:
objc_msgsend(person, @selector(coding));
二、相關函式
// 遍歷某個類所有的成員變數
class_copyivarlist
// 遍歷某個類所有的方法
class_copymethodlist
// 程式設計客棧獲取指定名稱的成員變數
class_getinstancevariable
// 獲取成員變數名
ivar_getname
// 獲取成員變數型別編碼
ivar_gettypeencoding
// 獲取某個物件成員變數的值
object_getivar
// 設定某個物件成員變數的值
object_setivar
// 給物件傳送訊息
objc_msgsend
三、相關應用
以上八種用法用**都實現了, 文末會貼出**位址.
runtime
四、**實現
要使用runtime,要先引入標頭檔案#import
4.1 更改屬性值
用 runtime 修改乙個物件的屬性值
unsigned int count = 0;
// 動態獲取類中的所有屬性(包括私有)
ivar *ivar = class_copyivarlist(_person.class, &count);
// 遍歷屬性找到對應字段
for (int i = 0; i < count; i ++)
}4.2 動態新增屬性
用 runtime 為乙個類新增屬性, ios 分類裡一般會這樣用, 我們建立乙個分類, nsobject+nnaddattribute.h, 並新增以下**:
- (void)setname:(nsstring *)name
- (nsstring *)name
這樣只要引用 nsobject+nnaddattribute.h, 用 nsobject 建立的物件就會有乙個 name 屬性, 我們可以直接這樣寫:
nsobject *person = [nsobject new];
person.name = @"以夢為馬";
4.3 動態新增方法
person 類中沒有 coding 方法,我們用 runtime 給 person 類新增了乙個名字叫 coding 的方法,最終再呼叫coding方法做出相應. 下面**的幾個引數需要注意一下:
- (void)buttonclick:(uibutton *)sender else }
// 編寫 codingoc 的實現
void codingoc(id self,sel _cmd)
4.4 交換方法的實現
某個類有兩個方法, 比如 person 類有兩個方法, coding 方法與 eating 方法, 我們用 runtime 交換一下這兩個方法, 就會出現這樣的情況, 當我們呼叫 coding 的時候, 執行的是 eating, 當我們呼叫 eating 的時候, 執行的是 coding, 如下面的動態效果圖.
method orimethod = class_getinstancemethod(_person.class, @selector(coding));
method curmethod = class_getin @selector(eating));
method_exchangeimplementations(orimethod, curmethod);
交換方法的實現
4.5 攔截並替換方法
這個功能和上面的其實有些類似, 攔截並替換方法可以攔截並替換同乙個類的, 也可以在兩個類之間進行, 我這裡用了兩個不同的類, 下面是簡單的**實現.
_person = [nnperson new];
_library = [nnlibrary new];
self.testlabeltext = [_library librarymethod];
method orimethod = class_getinstancemethod(_person.class, @selector(changemethod));
method curmethod = class_getinstancemethod(_library.class, @selector(librarymethod));
method_exchangeimplementations(orimethod, curmethod);
4.6 在方法上增加額外功能
這個使用場景還是挺多的, 比如我們需要記錄 app 中某乙個按鈕的點選次數, 這個時候我們便可以利用 runtime 來實現這個功能. 我這裡寫了個 uibutton 的子類, 然後在 + (void)load 中用 runtime 給它增加了乙個功能, 核心**及實現效果圖如下:
+ (void)load else
});}
在方法上增加額外功能
4.7 歸檔解檔
當我們使用 nscoding 進行歸檔及解檔時, 如果不用 runtime, 那麼不管模型裡面有多少屬性, 我們都需要對其實現一遍 encodeobject 和 decodeobjectforkey 方法, 如果模型裡面有 10000 個屬性, 那麼我們就需要寫 10000 句encodeobject 和 decodeobjectforkey 方法, 這個時候用 runtime, 便可以充分體驗其好處(以下只是核心**, 具體**請見 demo).
- (void)encodewithcoder:(nscoder *)acoder
free(ivars);
}- (instancetype)initwithcoder:(nscoder *)adecoder
} return self;
}4.8 字典轉模型
字典轉模型我們通常用的都是第三方, mjextension, yymodel 等, 但也有必要了解一下其實現方式: 遍歷模型中的所有屬性,根據模型的屬性名,去字典中查詢對應的 key,取出對應的值,給模型的屬性賦值。
/** 字典轉模型 **/
+ (instancetype)modelwithdict:(nsdictionary *)dict
} if ([value iskindofclass:[nsarray class]])
// 把模型陣列賦值給value
value = arrm;
}} // kvc 字典轉模型
if (value)
} return objc;
}上面的所有**都可以在這裡**: runtime 練習: nnruntimetest
總結本文標題: ios開發中runtime常用的幾種方法示例總結
本文位址:
iOS開發中runtime的使用
事實證明 1.傳送訊息 implementation viewcontroller void viewdidload end implementation uiimage image 載入分類到記憶體的時候呼叫 void load 注意 不能在分類中重寫系統方法imagenamed,因為會把系統的功...
iOS開發 runtime機制
runtime簡稱執行時。就是系統在執行的時候的一些機制,其中最主要的是訊息機制。對於c語言,函式的呼叫在編譯的時候會決定呼叫哪個函式 c語言的函式呼叫請看這裡 編譯完成之後直接順序執行,無任何二義性。oc的函式呼叫成為訊息傳送。屬於動態呼叫過程。在編譯的時候並不能決定真正呼叫哪個函式 事實證明,在...
iOS開發中Runtime的實際應用
runtime是objective c的乙個固有特性,及在編譯階段並不能確定真正呼叫的函式名,函式的呼叫在執行時才得到確認。所以我們可以看到,oc在編譯階段沒有報錯的情況下,會在執行過程中出現閃退和崩潰的錯誤,而c語言在編譯過程中就會報錯。ios的錯誤處理 編譯未出報錯,執行卻閃退 動態呼叫特性 c...