Objective-C一共分為3類:
1.instance對象(實例對象)
instance對象就是通過類alloc出來的對象,每次調用產生不同的對象占用兩塊不同的內存
instance對象在內存中存儲的信息包括
1.isa指針
2.其他成員變量
2.class對象(類對象)
class對象在內存中存儲的信息包括
1.isa指針
2.superclass指針
3.類的屬性(@property)
4.類的對象方法(instance method)
5.類的協議(protocol)
6.類的成員變量(ivar)
3.meta-class對象(元類對象)
meta-class對象和class對象的內存結構(所有的類型相同,只不過有些值是null)是一樣的,但是用途不一樣,在內存中存儲的信息主要包括
1.isa指針
2.superclass指針
3.類方法
查看Class是否為元類
#import <objc/runtime.h>
BOOL result =class_isMetaClass([NSObject class]);
class、meta-class對象的本質結構都是struct objc_class
Class object_getClass(id obj)
輸入參數 | 返回對象 |
---|---|
instance對象/字符串類名 | class對象 |
class對象 | meta-class對象 |
meta-class對象 | NSObject(基類)的meta-class對象 |
(Class)class、+ (Class)class
1> 返回的就是類對象
- (Class) {
return self->isa;
}
+ (Class) {
return self;
}
NSObject的底層實現
@interface NSObject{
Class isa;
}
Struct NSObject_IMPL{
Class isa;
}
//typedef struct objc_class *Class; //Class是objc_class類型的指針,isa的地址就是NSObject的指針地址,結構體的地址就是第一個成員的地址
sizeof是一個運算符,不是函數調用,傳入的是類型,編譯的時候就確定了,編譯完就是一個常數
#import <objc/runtime.h>
NSLog(@"%zd",class_getInstanceSize([NSObject class])); //獲取NSObject實例對象的成員變量所占用的大小為8字節
在iOS中堆空間分配內存都是16字節的倍數
#import <malloc/malloc.h>
NSLog(@"%zd",malloc_size((__bridge const void*)obj)); ////獲得obj指針指向內存的大小為16字節
方法調用軌跡:
instance的isa指向class:
當調用對象方法時,通過instance的isa找到class,最后找到對象方法的實現進行調用
class的isa指向meta-class:
當調用類方法時,通過class的isa找到meta-class,最后找到類方法的實現進行調用
isa指向:
1.instance的isa指向class
2.class的isa指向meta-class
3.meta-class的isa指向基類的meta-class
superclass指向
1.class的superclass指向父類的class
如果沒有父類,superclass指針為nil
2.meta-class的superclass指向父類的meta-class
基類的meta-class的superclass指向基類的class
instance調用對象方法的軌跡
isa找到class,方法不存在,就通過superclass找父類
class調用類方法的軌跡
isa找meta-class,方法不存在,就通過superclass找父類
打印一個對象的指針
Person *person =[[Person alloc]init];
Class personClass = [Person class];
Class personMetaClass = object_getClass(personClass);
//控制臺打印,查看person對象的isa地址
p/x (long)person->isa
p/x personClass
(long)person->isa & ISA_MASK = personClass地址
為什么person->isa!=personClass地址 ,還要& ISA_MASK?
在arm64架構之前,isa就是一個普通的指針,存儲著Class、Meta-Class對象的內存地址
從arm64架構開始,對isa進行了優化,變成了一個共用體(union)結構,還使用位域來存儲更多的信息
Objective-C對象指針轉換成C對象指針,只需要用一個橋接就可以了,(__bridge const void *)
//personClass->isa直接訪問,訪問不到需要定義一個結構體完成一次強制轉換
struct ly_objc_class{
Class isa;
Class superclass;
}
當Student的instance對象要調用Person的對象方法時,會先通過isa找到Student的class,然后通過superclass找到Person的class,找到對象方法的實現進行調用
當Student的class要調用Person的類方法時,會先通過isa找到Student的meta-class,然后通過superclass找到Person的meta-class,找到類方法的實現進行調用
struct ly_objc_class personClass2 =(__bridge struct ly_objc_class)personClass;
p/x personClass2->isa
p/x personMetaClass->isa
personClass2->isa & ISA_MASK = personMetaClass的地址//查看superclass的用法
struct ly_objc_class studentClass =(__bridge struct ly_objc_class)([Student class]);
p/x studentClass->superclass = personClass的地址