一:runtime簡介:也是面試必須會回答的部分面試
二:runtime的消息機制xcode
#import "ViewController.h" #import <objc/message.h> #import "Person.h" /* 總結: 1: runtime:必需要導入頭文件 <objc/message.h>,此頭文件中已經引入了<objc/runtime.h> 任何方法調用本質:發送一個消息,用runtime發送消息.OC底層實現經過runtime實現 驗證:方法調用,是否真的是轉換爲消息機制 runtime都有一個前綴,誰的事情使用誰 2:((NSObject *(*)(id, SEL))(void *)objc_msgSend)([NSObject class], @selector(alloc)); 此段代碼可簡化爲:objc_msgSend([NSObject class], @selector(alloc));,其中(NSObject *(*)(id, SEL))此爲一個函數指針,返回值類型爲NSObject *,參數爲(id, SEL)),id表明誰發送的消息 ,SEL:函數入口,發送什麼消息 xcode6以前,蘋果運行使用objc_msgSend.並且有參數提示 xcode6蘋果不推薦咱們使用runtime 3:解決消息機制方法提示步驟 查找build setting -> 搜索msg,設置爲NO,通常配置信息都在build setting中設置,build Phases通常是引入系統框架和設置參與編譯的.m文件,.h文件不參與編譯 最終生成消息機制,編譯器作的事情 最終代碼,須要把當前代碼從新編譯,用xcode編譯器,clang 4:runtime:方法都是有前綴,誰的事情誰開頭 開發中使用場景: 須要用到runtime,消息機制 1.裝逼 2.不得不用runtime消息機制,能夠調用系統API中或是框架中的私有方法 5:消息機制的調用過程: 面試: 方法調用流程 怎麼去調用eat方法 ,對象方法:類對象的方法列表 類方法:元類中方法列表 1.經過isa去對應的類中查找 2.註冊方法編號 3.根據方法編號去查找對應方法 4.找到只是最終函數實現地址,根據地址去方法區調用對應函數 過程:一個對象被初始化後,內部會有一個isa指針,指向類對象(類對象的方法列表),類對象中會有一個方法列表,此時會根據方法列表註冊方法編號,方法編號對應方法列表,根據方法編號查找對應的方法,找到的只是最終函數的實現地址,根據地址去內存中的方法區調用對應函數 內存的5大區 1.棧 2.堆 3.靜態區 4.常量區 5.方法區 1.棧:不須要手動管理內存,自動管理 2.堆,須要手動管理內存,本身去釋放 */ @interface ViewController () @end @implementation ViewController /** * 1:objc_getClass("Person")表示得到類對象,sel_registerName("alloc")表示註冊一個方法 2:調用eat:是對象調用eat,消息機制就是誰發送的什麼消息:objc_msgSend(p, @selector(eat)); */ - (void)viewDidLoad { [super viewDidLoad]; // Person *p = [Person alloc]; Person *p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc")); // p = [p init]; p = objc_msgSend(p, sel_registerName("init")); // 調用eat // [p eat]; objc_msgSend(p, @selector(eat)); // objc_msgSend(p, @selector(run:),20); } /** 1:一個對象的初始化方法可分解爲兩步:alloc 來開闢內存空間,init來初始化:id objc = [NSObject alloc];開闢內存空間的時候得到一個類對象,類對象在初始化獲得一個對象objc = [objc init]; 2:上述初始化的過程用runtime來實現: //id objc = [NSObject alloc]; id objc = objc_msgSend([NSObject class], @selector(alloc)); //objc = [objc init]; objc = objc_msgSend(objc, @selector(init)); * */ - (void)test { // id objc = [NSObject alloc]; id objc = objc_msgSend([NSObject class], @selector(alloc)); // objc = [objc init]; objc = objc_msgSend(objc, @selector(init)); } @end