Runtime的理解
Instance 對象實例
- id的本質是什么:
typedef struct objc_class *Class; struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }; typedef struct objc_object *id;
創(chuàng)建的一個對象或實例其實就是一個struct objc_object結構體弟劲,而我們常用的id也就是這個結構體指針几蜻。
這個結構體只有一個成員變量婿失,這是一個Class類型的變量isa,也是一個結構體指針睹限。
面向對象中每一個對象都必須依賴一個類來創(chuàng)建,因此對象的isa指針就指向對象所屬的類根據(jù)這個類模板能夠創(chuàng)建出實例變量拾弃、實例方法等值桩。
例如:
NSString *str = @"Hello World";
str對象本質就是一個objc_object結構體,而這個結構體的成員變量isa指針則表明了str is a NSString, 因此這個isa就指向了NSString類豪椿,這個NSString類其實就是類對象
Class object/metaclass
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;
/* Use `Class` instead of `struct objc_class *` */
struct objc_class結構里存放的數(shù)據(jù)稱為元數(shù)據(jù)(metadata)
該結構體的第一個成員變量也是isa指針奔坟,這就說明了Class本身其實也是一個對象,我們稱之為類對象搭盾,類對象在編譯期產(chǎn)生用于創(chuàng)建實例對象咳秉,是單例
- isa指針又指向什么:
image
通過上圖我們可以清晰的看出來一個實例對象也就是struct objc_object結構體它的isa指針指向類對象,類對象的isa指針指向了元類鸯隅,super_class指針指向了父類的類對象澜建,而元類的super_class指針指向了父類的元類,那元類的isa指針又指向了什么
通過上圖我們可以看出整個體系構成了一個自閉環(huán)蝌以,如果是從NSObject中繼承而來的上圖中的Root class就是NSObject炕舵。至此,整個實例跟畅、類對象咽筋、元類的概念也就講清了。
我們?nèi)绾潍@取isa指針的指向對象呢碍彭?
OBJC_EXPORT BOOL class_isMetaClass(Class cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
OBJC_EXPORT Class object_getClass(id obj)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
class_isMetaClass用于判斷Class對象是否為元類晤硕,object_getClass用于獲取對象的isa指針指向的對象
- runtime的其它用法1
1.Runtime使用:objc_getClassList
int objc_getClassList(Class *buffer, int bufferCount)
作用:獲取已經(jīng)注冊的類
參數(shù):1.buffer 已分配好內(nèi)存空間的數(shù)組
2.bufferCount 數(shù)組中可存放元素的個數(shù),返回值是注冊的類的總數(shù)
注意: 當bufferCount 值小于注冊的類的總數(shù)時庇忌,獲取到的是注冊類的集合的任意子集
第一個參數(shù)傳NULL時將會獲取到當前注冊的所有的類舞箍,此時可存儲元素的個數(shù)為0,因此第二個參數(shù)可傳0皆疹,返回值為當前注冊的所有類的總數(shù)
class_getName(Class cls) 獲取每個類的名稱
class_getSuperclass(Class cls) 獲取到某一個類的所有子類
Class *objc_copyClassList(unsigned int *outCount)
作用:
獲取所有已經(jīng)注冊的類疏橄,
傳入NULL和0跟getClassList是一樣的效果