目錄
1、Runtime存在的意義是什麼?
2、根元類的isa指標指向誰?
3、根元類的superClass指標指向誰?
4、函式四要素都是什麼?
5、例項方法去哪裡找?
1、Runtime存在的意義是什麼?
答:Objective-C 是一門動態語言,它會將一些工作放在程式碼執行時才處理而並非編譯時。也就是說,有很多類和成員變數在我們編譯的時是不知道的,而在執行時,我們所編寫的程式碼會轉換成完整的確定的程式碼執行。因此,只有編譯器是不夠的,我們還需要一個執行時系統(Runtime system)來處理編譯後的程式碼。 這就是 Objective-C Runtime 系統存在的意義,它是整個Objc執行框架的一塊基石。平時編寫的OC程式碼,底層都是由他實現的,如:
[receiver message];
//底層執行時會被編譯器轉化為:
objc_msgSend(receiver, selector)
//如果其還有引數比如:
[receiver message:(id)arg...];
//底層執行時會被編譯器轉化為:
objc_msgSend(receiver, selector, arg1, arg2, ...)
複製程式碼
2、根元類的isa指標指向誰?
答: 見下一問3、根元類的superClass指標指向誰?
答:這兩題一起回答。首先看下圖:先說幾個概念:
1)supercalss : 父類
2)subclass: 子類
3)isa : 概念不好說,官方文件說的也不清晰。作用是根據 isa 指標就可以找到物件所屬的類,但是isa指標在程式碼執行時並不總指向例項物件所屬的型別,所以不能依靠它來確定型別,要想確定型別還是需要用物件的 -class 方法。(PS:KVO 的實現機理就是將被觀察物件的isa指標指向一箇中間類而不是真實型別。)
4)class : 類,一個執行時類中關聯了它的父類指標、類名、成員變數、方法、快取以及附屬的協議。(一個例項物件是一個類的例項)
5)meta class :元類,Objc 類本身也是一個物件
,類物件所屬的類就叫做元類(一個類是元類的例項)
第一列是類的例項變數,如:[Person new]或者[[Person alloc] init]出來的物件;
第二列是類本身,存放父類指標、類名、成員變數、方法、快取以及附屬的協議的資訊;
第三列是元類
- 1)isa路線:
- 例項物件的isa指向Class
- Class的isa指向Meta Class
- Meta Class的isa指向根元類Root Meta Class
- 根元類的isa指向自己
- 2)superclass路線:
- 例項物件沒有superclass ;
- 例項物件所在的類,存在superclass,類的superclass後面會指向Root Class,Root Class的super Class是nil;
- 元類也存在superclass,元類的superclass後面會指向Root Meta Class,而Root Meta Class的superclass卻是Root Class。
- 例項物件沒有superclass ;
所以:
- 根元類的isa指標指向自己
- 根元類的superclass指向root class
- 根類的isa指向根元類
- 根類的superclass指向nil
附舊版Class結構:
typedef struct objc_class *Class;
Class 其實是指向 objc_class 結構體的指標。objc_class 的資料結構如下:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
複製程式碼
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// A pointer to an instance of a class.
typedef struct objc_object *id;
複製程式碼
-
Class是一個指向objc_class(類)結構體的指標,而id是一個指向objc_object(物件)結構體的指標。
-
objec_object(物件)中isa指標指向的類結構稱為objec_class(該物件的類),其中存放著普通成員變數與物件方法 (“-”開頭的方法)。
-
objec_class(類)中isa指標指向的類結構稱為metaclass(該類的元類),其中存放著static型別的成員變數與static型別的方法 (“+”開頭的方法)。
附圖:
舊版Class
4、函式四要素都是什麼?
答:函式名,函式引數,引數型別,返回值型別(PS:ObjC一般叫方法,不叫函式)OC method簡單介紹
typedef struct objc_method *Method;
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE; //方法名
char *method_types OBJC2_UNAVAILABLE; //方法型別
IMP method_imp OBJC2_UNAVAILABLE; //方法實現
}
複製程式碼
objc_method 儲存了方法名,方法型別和方法實現。
方法名型別為 SEL
方法型別 method_types 是個 char 指標,儲存方法的引數型別和返回值型別 method_imp 指向了方法的實現,本質是一個函式指標 Ivar Ivar 是表示成員變數的型別。
typedef struct objc_ivar *Ivar;
struct objc_ivar {
char *ivar_name OBJC2_UNAVAILABLE;
char *ivar_type OBJC2_UNAVAILABLE;
int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
}
複製程式碼
其中 ivar_offset 是基地址偏移位元組
IMP
IMP在objc.h中的定義是:
typedef id (*IMP)(id, SEL, ...);
複製程式碼
它就是一個函式指標,這是由編譯器生成的。當你發起一個 ObjC 訊息之後,最終它會執行的那段程式碼,就是由這個函式指標指定的,而 IMP 這個函式指標就指向了這個方法的實現。
5、例項方法去哪裡找?
答:其所屬的類的方法表擴充
問:oc是如何找到需要執行哪個方法的?
答:當需要執行某個例項方法的時候(類方法類似),oc會先去該類的方法的快取列表裡面查詢,若找到了,則執行,否則,去該類的方法列表中查詢是否存在該方法,存在,執行該方法並更新方法快取列表,否則,去該父類快取以及父類方法列表查詢,直到根類,若還未找到,則啟用動態解析以及訊息轉發流程,若還是失敗,報unrecognized selector異常
聯絡方式
郵箱: adrenine@163.com
郵箱: holaux@gmail.com
郵箱: ledahapple@icloud.com