一咬腋、runtime簡介
存在的意義
? ? ? ? Objective-C語言中玩裙,許多工作是在運行時執(zhí)行的盐类,所以僅有編譯器還不行,需要Runtime(運行時系統(tǒng))來執(zhí)行編譯后的代碼寓落。
版本
? ? ? ? legacy 運行在較老的32位程序中
? ? ? ? modern運行在ios和OS X10.5之后的64位程序中
二括丁、與Runtime的交互方式
Objective-C源代碼
? ? ? ? ?編譯器在編譯源代碼時,為實現(xiàn)動態(tài)語言特性伶选,會創(chuàng)建一些數(shù)據(jù)結(jié)構(gòu)和函數(shù)史飞,它們會在程序運行時被使用。
Runtime的函數(shù)
? ? ? ? ? ?Runtime系統(tǒng)由一系列函數(shù)和數(shù)據(jù)結(jié)構(gòu)組成具有接口的動態(tài)共享庫仰税。
? ? ? ? ? ?具體內(nèi)容參閱Objective-C Runtime Reference
NSObject的方法
? ? ? ? ? ?NSObject類中有許多方法起到了抽象接口的作用构资。如:description
? ? ? ? ? ?獲取類的信息。如:class陨簇、isKindOfClass吐绵、isMemberOfClass
三、Runtime術(shù)語
SEL
? ? ? ? ? ?是selector在Objective-C中的數(shù)據(jù)類型。
? ? ? ? ? ?selector是方法選擇器己单,相當(dāng)于區(qū)分方法的ID唉窃。
? ? ? ? ? ?是一個結(jié)構(gòu)體的指針 ? ?typedef struct objc_selector *SEL
Class
? ? ? ? ?是一個結(jié)構(gòu)體的指針? typedef struct objc_class ?*Class
? ? ? ? ?Class isa OBJC_ISA_AVAILABILITY;
? ? ? ? ?objc類本身同時也是一個對象;元類是類對象所屬的類型纹笼,表述類對象本身所具備的元數(shù)據(jù)纹份;每個類對象僅有一個類對象;?每個類對象僅有一個與之相關(guān)的元素廷痘。
? ? ? ? ?OBJC2_UNAVAILABLE ? ? ?是Objc中對系統(tǒng)運行版本進(jìn)行約束的宏定義
? ? ? ? ?Class ?super_class ? ? OBJC2_UNAVAILABLE;//超類指針
? ? ? ? ?const ?char*name ? ? ?OBJC2_UNAVAILABLE;//類名?
? ? ? ? ?long version OBJC2_UNAVAILABLE;// 類的版本信息蔓涧,默認(rèn)為0
? ? ? ? ?long info ? OBJC2_UNAVAILABLE;// 類信息,供運行期使用的一些位標(biāo)識
? ? ? ? ?long instance_size ?OBJC2_UNAVAILABLE;// 該類的實例變量大小
? ? ? ? ?struct objc_ivar_list *ivarsOBJC2_UNAVAILABLE;// 該類的成員變量鏈表
? ? ? ? struct objc_method_list **methodListsOBJC2_UNAVAILABLE;// 方法定義的鏈表
? ? ? ? struct objc_cache *cacheOBJC2_UNAVAILABLE;// 方法緩存
? ? ? ? struct objc_protocol_list *protocolsOBJC2_UNAVAILABLE;// 協(xié)議鏈表
? struct ?objc_ivar_list *ivars ? OBJC2_UNAVAILABLE;//成員變量列表
??
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;//方法列表
IMP
? ? ? ? ? ? ?由編譯器生成的函數(shù)指針
? ? ? ? ? ? ?定義:typedef ?id (*IMP)(id,SEL,...);
? ? ? ? ? ? ?該指針指向某個方法的實現(xiàn)部分
Method
? ? ? ? ? 類中某個方法的類型
? ? ? ? ? 是一個結(jié)構(gòu)體的指針 ?typedef ?struct objc_method *Method;
? ? ? ? ? ?method_name ?方法名
? ? ? ? ? ?method_types ?方法的參數(shù)類型和返回值類型
? ? ? ? ? ? method_imp 指向方法實現(xiàn)的函數(shù)指針
Ivar
? ? ? ? ? 類中實例變量的類型
? ? ? ? ? 定義:typedef struct objc_ivar*Ivar;
Cache
? ? ? ? 用于緩存最近使用的方法笋额。一個接收者對象接收到一個消息時元暴,它會根據(jù)isa指針去查找能夠響應(yīng)這個消息的對象。在實際使用中兄猩,這個對象只有一部分方法是常用的昨寞,很多方法其實很少用或者根本用不上。這種情況下厦滤,如果每次消息來時援岩,我們都是methodLists中遍歷一遍,性能勢必很差掏导。這時享怀,cache就派上用場了。在我們每次調(diào)用過一個方法后趟咆,這個方法就會被緩存到cache列表中添瓷,下次調(diào)用的時候runtime就會優(yōu)先去cache中查找,如果cache沒有值纱,才去methodLists中查找方法鳞贷。這樣,對于那些經(jīng)常用到的方法的調(diào)用虐唠,但提高了調(diào)用的效率搀愧。
? ? ? 簡單記:方法被調(diào)用時的優(yōu)化,即當(dāng)一個方法被調(diào)用時疆偿,首先在Cache中查找咱筛,沒有時再去方法列表中查找。
? ? ? ? ? ?定義:typedef struct objc_cache *Cache;
更多:
isa:需要注意的是在Objective-C中杆故,所有的類自身也是一個對象迅箩,這個對象的Class里面也有一個isa指針,它指向metaClass(元類)处铛,我們會在后面介紹它饲趋。
super_class:指向該類的父類拐揭,如果該類已經(jīng)是最頂層的根類(如NSObject或NSProxy),則super_class為NULL奕塑。
version:我們可以使用這個字段來提供類的版本信息堂污。這對于對象的序列化非常有用,它可是讓我們識別出不同類定義版本中實例變量布局的改變爵川。
四、消息
objc_msgSend函數(shù)
?Objc中發(fā)送消息語句[receiver message]會被編譯器轉(zhuǎn)化成objc_msgSend(receiver,@selector(message));
? ?四種形態(tài):
? ? ? ? ? ? ? ?objc_msgSend 給本類發(fā)送消息息楔,返回一個簡單值;
? ? ? ? ? ? ? ?objc_msgSend_fpret ?給本類發(fā)送消息寝贡,返回的是浮點數(shù);?
? ? ? ? ? ? ? ?objc_msgSend_stret 給本類發(fā)送消息值依,返回一個結(jié)構(gòu)體類型的值圃泡;
? ? ? ? ? ? ? ?objc_msgSendSuper 給父類發(fā)送一個消息,返回一個簡單值愿险;
? ? ? ? ? ? ? ?objc_msgSendSuper_stret 給父類發(fā)送一個消息颇蜡,返回一個結(jié)構(gòu)體類型的值
執(zhí)行過程:
? ? ? ? ? ? 檢測selector是不是要忽略。(如 Mac OS X 開發(fā)辆亏,有垃圾回收就不用 retain风秤,release函數(shù)了)
? ? ? ? ? ? 檢測target是不是nil對象。objc的特性是允許對一個nil對象執(zhí)行任何一個方法不會Crash扮叨,因為會被忽略掉缤弦。
? ? ? ? ? ? 從cache里面找
? ? ? ? ? ? 如果cache找不到就從下一個方法列表中找
? ? ? ? ? ? 如果方法列表找不到就到超類的方法列表中找,一直找彻磁,直到找到NSObject類為止
? ? ? ? ? ? 如果還找不到就要開始進(jìn)入動態(tài)方法解析了
方法中的隱藏參數(shù)
? ? ? ? ? ? 當(dāng)objc_msgSend函數(shù)找到對應(yīng)的實現(xiàn)時碍沐,將直接調(diào)用該方法,同時將參數(shù)傳遞給方法衷蜓。同時還將兩個隱藏的參數(shù)傳遞過去
? ? ? ? ? ? self ?指向接收消息的對象
? ? ? ? ? ? _cmd 消息的SEL值
獲取方法地址
? ? NSObject類中有methodForSelector:實例方法累提,該方法返回某個方法對應(yīng)的IMP。
五磁浇、類型編碼
類型編碼
? ? ? ?編譯器使用@encode對返回值類型斋陪、參數(shù)類型進(jìn)行編碼;? Objective-C 類型編碼表
? ? ? ?輸出@encode 用%s
例如
struct MyStruct{ ? char c;} 置吓;用于參考
@encode(int) ? ? ? ? ? ? ? ? ? ? ? ? ? ?i ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int 類型
@encode(int*) ? ? ? ? ? ? ? ? ? ? ? ? ? ?^i ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 一個指針類型
@encode(struct MyStruct) ? ? ? ? ? {MyStruct= c} ? ? ? ? ? ? ? ? ? ? ? ? ? ?一個無符號字符
@encode(MessageTest) ? ? ? ? ? ? ? {MessageTest=#} ? ? ? ? ? ? ? ? ? ? ?一個類對象(類)
@encode(NSStringEncoding) ? ? ? ? Q ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 無符號長整型
......具體參閱類型編碼表
六鳍贾、動態(tài)方法解析
動態(tài)方法解析
? ? ? ? ?在自定義類中聲明一個方法,但并不在實現(xiàn)部分實現(xiàn)交洗。
? ? ? ? ?在程序運行時為方法添加實現(xiàn)骑科。
待續(xù)。构拳。咆爽。
@encode(MessageTest)