在了解OC对象在内存的本质后,那么我们进一步思考,OC对象是怎么分类的呢?每个类的作用,以及之间的联系又是怎么样呢?
Objective-C中的对象,简称OC对象,主要可以分为3种:
- instance对象(实例对象)
- class对象(类对象)
- meta-class对象(元类对象)
instance对象
- instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
- object1、object2是NSObject的instance对象(实例对象)它们是不同的两个对象,分别占据着两块不同的内存。
如图我们可以看到p1和p2是通过JJPerson的alloc方法创建出来的instance对象(实例对象),它们是两个不同的对象,有着不同的内存地址。
instance对象的内容
每个对象内部都有isa指针,instance对象在内存中存储的信息包括:
- isa指针
- 其他成员变量的值
isa排在首位,所以isa所指向的地址也是instance对象所在的地址,指针object1里存放的就是isa的地址值
类对象
- 创建类对象的方式:
Class class1 = [person class];
Class class2 = [NSObject clasd]
Class class3 = object_getClass(person)
NSLog(@"class - %p %p %p",class1,class2,class3);
- 一个类的类对象是统一的,也就是说只有一个,每个类在内存中有且只有一个类对象。
- class方法不管调用多少次返回的一直是class对象,即类对象:
Class objectClass = [[NSObject class]class]
- 类对象在内存中存储的信息主要包括:
- isa指针
- superclass指针
- 类的属性信息(@property)
- 类的对象方法信息(instance method)
- 类的协议信息(protocol)
- 类的成员变量信息(ivar,不是指的是成员变量的值,值存储在实例对象中,这里存储的是成员变量的名称等)
meta-class对象(元类对象)
元类对象是通过runtime的object_getClass方法获取的,和类对象不同的是,类对象获取时需要传入的参数是实例对象,而获取元类对象时则要把类对象作为参数传入。如下图我们可以看到,元类对象在整个内存中也只有一份。
- 获取元类对象,参数里需要传类对象:
Class metaClass = object_getClass([NSObject class]);
- 每个类在内存中有且只有一个meta-class对象
- meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:
- isa指针
- superclass指针
- 类方法信息(加号方法)
另外runtime还提供了一个class_isMateClass的方法来方便我们判断,这个类是否是元类对象
- 查看Class是否为meta-class
#import <objc/runtime.h>
BOOL result = class_isMetaClass([NSObject class]);
object_getClass内部实现
- objc_getClass返回的是isa指针,传入字符串名,返回对应的类对象。
- object_getClass传入的可能是实例对象,类对象和元类对象,如果是实例对象返回class对象,如果是class对象,返回meta-class对象,如果是meta-class对象,返回NSObject(基类)的meta-class对象。
网友评论