對象、類寂曹、元類读处、根元類
的關(guān)系
先溫習(xí)下這個(gè)圖
先背背圖
-
類的本質(zhì)
首先準(zhǔn)備可調(diào)試objc
源碼,配置可執(zhí)行的objc源碼
#import <Foundation/Foundation.h>
#import "PHPerson.h"
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
PHPerson * phPerson = [PHPerson alloc];
Class pClass = object_getClass(phPerson);
}
return 0;
}
cd到main.m
所在目錄clang
命令:
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m
main.m
文件輸出.cpp如圖
PHPerson * phPerson = ((PHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("PHPerson"), sel_registerName("alloc"));
Class
是什么?在objc源碼
找到
typedef struct objc_class *Class
探知Class
的類型是objc_class
.
那么 objc_class
又是什么碌燕?
繼續(xù)跟進(jìn):
可知
objc_class
繼承于objc_object
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
....//省略
}
總結(jié): 類的本質(zhì)是objc_class
類型的結(jié)構(gòu)體折汞,objc_class
繼承于objc_object
倔幼;
問題:不是說對象繼承與NSObject?跟objc_object有什么關(guān)系爽待?
1.同樣在objc源碼
中找到NSObject
的定義
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
NSObject
中存在Class
類型的成員變量isa
损同,Class
又是objc_class
類型的結(jié)構(gòu)體且objc_class
繼承于objc_object
的結(jié)構(gòu)體;
結(jié)論:NSObject
類是OC版本
的objc_object
問題:
isa
明明是isa_t
類型的,為什么注釋了一句Class ISA
鸟款?
1.萬物皆對象膏燃,用繼承于objc_object
的Class
接收是沒問題的
2.強(qiáng)轉(zhuǎn),方便isa走位
時(shí)返回類的類型
-
類的結(jié)構(gòu)
objc_class
的定義
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
....
}
1.Class ISA
- 不但實(shí)例對象中有isa指針何什,類對象中也有
isa指針關(guān)聯(lián)著元類
,
Class
本身就是一個(gè)指針组哩,占用8字節(jié)
2.Class superclass
- 顧名思義就是類的父類(一般為
NSObject
)superclass
是Class
類型,所以占用8字節(jié)
3.cache_t cache
-cache_t
是一個(gè)結(jié)構(gòu)體,內(nèi)存長度有所有元素決定:_buckets
是一個(gè)指針伶贰,占用8字節(jié)蛛砰;mask_t
是個(gè)int類型
,_mask
占用4字節(jié)
黍衙;_occupied
占用4字節(jié)
struct cache_t {
#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
explicit_atomic<struct bucket_t *> _buckets;//8字節(jié)
explicit_atomic<mask_t> _mask;//4字節(jié)
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
explicit_atomic<uintptr_t> _maskAndBuckets;
#if __LP64__
uint16_t _flags; //2字節(jié)
#endif
uint16_t _occupied;//2字節(jié)
...
};
typedef uint32_t mask_t; // x86_64 & arm64 asm are less efficient with 16-bits
合計(jì):cache_t
占用16字節(jié)
4.class_data_bits_t bits
根據(jù)字母意思就是大小內(nèi)存猜下也就是存數(shù)據(jù)
struct class_data_bits_t {
friend objc_class;
// Values are the FAST_ flags above.
uintptr_t bits;
private:
bool getBit(uintptr_t bit) const
{
return bits & bit;
}
void setBits(uintptr_t set) {
__c11_atomic_fetch_or((_Atomic(uintptr_t) *)&bits, set, __ATOMIC_RELAXED);
}
public:
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
void setData(class_rw_t *newData)
{
ASSERT(!data() || (newData->flags & (RW_REALIZING | RW_FUTURE)));
// Set during realization or construction only. No locking needed.
// Use a store-release fence because there may be concurrent
// readers of data and data's contents.
uintptr_t newBits = (bits & ~FAST_DATA_MASK) | (uintptr_t)newData;
atomic_thread_fence(memory_order_release);
bits = newBits;
}
};
class_data_bits_t
存儲(chǔ)的就是類相關(guān)的東西
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
點(diǎn)擊進(jìn)入源碼
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint16_t witness;
#if SUPPORT_INDEXED_ISA
uint16_t index;
#endif
explicit_atomic<uintptr_t> ro_or_rw_ext;
Class firstSubclass;
Class nextSiblingClass;
private:
using ro_or_rw_ext_t = objc::PointerUnion<const class_ro_t *, class_rw_ext_t *>;
const ro_or_rw_ext_t get_ro_or_rwe() const {
return ro_or_rw_ext_t{ro_or_rw_ext};
}
void set_ro_or_rwe(const class_ro_t *ro) {
ro_or_rw_ext_t{ro}.storeAt(ro_or_rw_ext, memory_order_relaxed);
}
void set_ro_or_rwe(class_rw_ext_t *rwe, const class_ro_t *ro) {
// the release barrier is so that the class_rw_ext_t::ro initialization
// is visible to lockless readers
rwe->ro = ro;
ro_or_rw_ext_t{rwe}.storeAt(ro_or_rw_ext, memory_order_release);
}
class_rw_ext_t *extAlloc(const class_ro_t *ro, bool deep = false);
public:
void setFlags(uint32_t set)
{
__c11_atomic_fetch_or((_Atomic(uint32_t) *)&flags, set, __ATOMIC_RELAXED);
}
void clearFlags(uint32_t clear)
{
__c11_atomic_fetch_and((_Atomic(uint32_t) *)&flags, ~clear, __ATOMIC_RELAXED);
}
// set and clear must not overlap
void changeFlags(uint32_t set, uint32_t clear)
{
ASSERT((set & clear) == 0);
uint32_t oldf, newf;
do {
oldf = flags;
newf = (oldf | set) & ~clear;
} while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&flags));
}
class_rw_ext_t *ext() const {
return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>();
}
class_rw_ext_t *extAllocIfNeeded() {
auto v = get_ro_or_rwe();
if (fastpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>();
} else {
return extAlloc(v.get<const class_ro_t *>());
}
}
class_rw_ext_t *deepCopy(const class_ro_t *ro) {
return extAlloc(ro, true);
}
const class_ro_t *ro() const {//成員變量(猜的)
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>()->ro;
}
return v.get<const class_ro_t *>();
}
void set_ro(const class_ro_t *ro) {//類方法列表(猜)
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
v.get<class_rw_ext_t *>()->ro = ro;
} else {
set_ro_or_rwe(ro);
}
}
const method_array_t methods() const {//實(shí)例方法列表
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->methods;
} else {
return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
}
}
const property_array_t properties() const {//屬性列表
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->properties;
} else {
return property_array_t{v.get<const class_ro_t *>()->baseProperties};
}
}
const protocol_array_t protocols() const {//協(xié)議列表
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->protocols;
} else {
return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
}
}
};
這個(gè)信息也很重要 特別是ro()
struct class_rw_ext_t {
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
char *demangledName;
uint32_t version;
};
-
類的相關(guān)方法
如圖添加成員變量
nickName
泥畅,屬性name
,類方法+ (void)walk
和實(shí)例方法- (void)fly
bits
剛好是類的內(nèi)存首地址+isa、superclass琅翻、cache
的內(nèi)存長度==>0x100003250
+32字節(jié)
=0x100003270
通過指針地址訪問data()
獲取類信息的數(shù)據(jù)
訪問class_rw_t
的properties屬性
得到對象的屬性,可以看出是個(gè)數(shù)組類型property_array_t
變量中為啥只有name
沒有nickName
方椎,猜測這個(gè)成員變量nickName
還是在這塊存著聂抢,發(fā)現(xiàn)這個(gè)玩意兒
const class_ro_t *ro() const {//成員變量(猜的)
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>()->ro;
}
return v.get<const class_ro_t *>();
}
底層:
struct protocol_list_t {
// count is pointer-sized by accident.
uintptr_t count;
protocol_ref_t list[0]; // variable-size
size_t byteSize() const {
return sizeof(*this) + count*sizeof(list[0]);
}
protocol_list_t *duplicate() const {
return (protocol_list_t *)memdup(this, this->byteSize());
}
typedef protocol_ref_t* iterator;
typedef const protocol_ref_t* const_iterator;
const_iterator begin() const {
return list;
}
iterator begin() {
return list;
}
const_iterator end() const {
return list + count;
}
iterator end() {
return list + count;
}
};
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;
method_list_t * baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;//這是存在成員變量的數(shù)組
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
// This field exists only when RO_HAS_SWIFT_INITIALIZER is set.
_objc_swiftMetadataInitializer __ptrauth_objc_method_list_imp _swiftMetadataInitializer_NEVER_USE[0];
_objc_swiftMetadataInitializer swiftMetadataInitializer() const {
if (flags & RO_HAS_SWIFT_INITIALIZER) {
return _swiftMetadataInitializer_NEVER_USE[0];
} else {
return nil;
}
}
method_list_t *baseMethods() const {
return baseMethodList;
}
class_ro_t *duplicate() const {
if (flags & RO_HAS_SWIFT_INITIALIZER) {
size_t size = sizeof(*this) + sizeof(_swiftMetadataInitializer_NEVER_USE[0]);
class_ro_t *ro = (class_ro_t *)memdup(this, size);
ro->_swiftMetadataInitializer_NEVER_USE[0] = this->_swiftMetadataInitializer_NEVER_USE[0];
return ro;
} else {
size_t size = sizeof(*this);
class_ro_t *ro = (class_ro_t *)memdup(this, size);
return ro;
}
}
};
中的這個(gè)const ivar_list_t * ivars
通過訪問ivars
這個(gè)ivars
的列表中里具體都有啥?
-
類的方法
打印ro
的baseMethodList
擦+walk()
類方法找不到了
找元類的方法試下:
總結(jié):類方法
可以理解成元類對象
的實(shí)例方法
,因此存在元類
中
成員變量
存放在ivar
屬性
存放在property
棠众,同時(shí)也會(huì)存一份在ivar
涛浙,并生成setter、getter
方法對象方法
存放在類
里面類方法
存放在元類
里面
- 利用底層開放的API可以驗(yàn)證以上結(jié)論
void testObjc_copyIvar_copyProperies(Class cls) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(cls, &count);
for (unsigned int i=0; i < count; i++) {
Ivar const ivar = ivars[i];
//獲取實(shí)例變量名
const char*cName = ivar_getName(ivar);
NSString *ivarName = [NSString stringWithUTF8String:cName];
NSLog(@"class_copyIvarList:%@",ivarName);
}
free(ivars);
unsigned int pCount = 0;
objc_property_t *properties = class_copyPropertyList(cls, &pCount);
for (unsigned int i=0; i < pCount; i++) {
objc_property_t const property = properties[i];
//獲取屬性名
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
//獲取屬性值
NSLog(@"class_copyProperiesList:%@",propertyName);
}
free(properties);
}
void testObjc_copyMethodList(Class cls) {
unsigned int count = 0;
Method *methods = class_copyMethodList(cls, &count);
for (unsigned int i=0; i < count; i++) {
Method const method = methods[i];
//獲取方法名
NSString *key = NSStringFromSelector(method_getName(method));
NSLog(@"Method, name: %@", key);
}
free(methods);
}
void testInstanceMethod_classToMetaclass(Class cls) {
const char *className = class_getName(cls);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getInstanceMethod(cls, @selector(walk));
Method method2 = class_getInstanceMethod(metaClass, @selector(fly));
Method method3 = class_getInstanceMethod(cls, @selector(walk));
Method method4 = class_getInstanceMethod(metaClass, @selector(fly));
NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);
NSLog(@"%s",__func__);
}
void testClassMethod_classToMetaclass(Class cls) {
const char *className = class_getName(cls);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getClassMethod(cls, @selector(walk));
Method method2 = class_getClassMethod(metaClass, @selector(fly));
Method method3 = class_getClassMethod(cls, @selector(walk));
Method method4 = class_getClassMethod(metaClass, @selector(fly));
NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);
NSLog(@"%s",__func__);
}
void testIMP_classToMetaclass(Class cls) {
const char *className = class_getName(cls);
Class metaClass = objc_getMetaClass(className);
IMP imp1 = class_getMethodImplementation(cls, @selector(walk));
IMP imp2 = class_getMethodImplementation(metaClass, @selector(fly));
IMP imp3 = class_getMethodImplementation(cls, @selector(walk));
IMP imp4 = class_getMethodImplementation(metaClass, @selector(fly));
NSLog(@"%p-%p-%p-%p",imp1,imp2,imp3,imp4);
NSLog(@"%s",__func__);
}
- 其實(shí)直接用
clang編譯
也能看出點(diǎn)東西 - 關(guān)于
v@:
這個(gè)玩意摄欲,在蘋果開發(fā)者文檔上也有介紹