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
struct objc_class.pngClass 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:
isa.png当调用类方法时,通过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?
weiyu.png在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的地址
网友评论