
Objective-C中的对象,简称OC对象,主要可以分为3种
instance对象(实例对象)class对象(类对象)meta-class对象(元类对象)instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
NSLog(@"%p", obj1);
NSLog(@"%p", obj2);打印结果会输出
0x1004992a0
0x1004974f0由此可以看出,obj1和obj2是两个不同的对象,分别占据着两块不同的内存。
而instance对象在内存中存储的信息包括
isa指针_age = 5,这个5就是存在于实例对象中的查看以下代码中的内存地址
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = [NSObject class];
Class objectClass4 = object_getClass(object1);
Class objectClass5 = object_getClass(object2);在控制台调试打印地址
(lldb) p/x (long)objectClass1
(long) $2 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass2
(long) $3 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass3
(long) $4 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass4
(long) $5 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass5
(long) $6 = 0x00007fff8a20f140经过调试可以发现5个Class类指向同一个地址值0x00007fff8a20f140,它和instance对象的区别是instance对象是alloc分配的内存空间,每个实例对象都占用不同的空间,但是Class一个类只占用一份内存空间。
objectClass1~objectClass5都是NSObject的Class对象(类对象)Class对象Class对象在内存中存储的信息主要包括 isa指针superclass指针(@property) (instance method) (protocol) (ivar) class和meta-class内存地址值比较
Class objectClass = [NSObject class];
Class objectMetaClass = object_getClass([NSObject class]);
NSLog(@"%p", objectClass);
NSLog(@"%p", objectMetaClass);0x7fff8a20f140
0x7fff8a20f0f0对比发现,Class和meta-class的内存地址不一样。我们可以进行如下总结 :
objectMetaClass是NSObject的meta-class对象(元类对象)meta-class对象meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存总存储的主要信息包括 isa指针superclass指针(class method) 获取元类的内存地址只能通过object_getClass([NSObject class])进行获取,通过[[NSObject class] class]这种获取方法是错误的。
Class objectClass = [NSObject class];
Class objectWrongMetaClass = [[NSObject class] class];
Class objectMetaClass = object_getClass([NSObject class]);
NSLog(@"%p", objectClass);
NSLog(@"%p", objectWrongMetaClass);
NSLog(@"%p", objectMetaClass);0x7fff8a20f140
0x7fff8a20f140
0x7fff8a20f0f0instance(实例对象)里。Class(类对象)里。meta-class(元类对象)里。根据上面可知,对象方法存储在class的内存里,类方法存在于meta-class内存里。问题来了,假如现在有一个Person类的实例化对象p1,如果想用p1调用Person类的对象方法personMethod该如何调用呢?毕竟,p1是存储在实例化对象instance内存中的,而personMethod方法是存储于Person类的内存中的。
实际上instance实例的对象的isa指针指向class,找到class类以后,再在class类中找存储于其中的对象方法方法进行调用。
调用类方法的过程也是如此,class类通过其内部的isa指针找到meta-class类中存储的类方法,然后再进行调用。
至此,就可以回答上面的问题了。
instance对象的isa指向class。 对象方法时,通过instance的isa找到class,再找到对象方法进行调用。class对象的isa指向meta-class。 类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用。meta-class对象的isa指向基类的meta-class对象。有如下两个类,继承关系如下 :
Student->Person->NSobject
@interface Person : NSObject
- (void)personMethod;
+ (void)personClassMethod;
@end
@implementation Person
- (void)personMethod {};
+ (void)personClassMethod {};
@end@interface Student : Person
- (void)studentMethod;
+ (void)studentClassMethod;
@end
@implementation Student
- (void)studentMethod {};
+ (void)studentClassMethod {};
@end创建一个实例student
Student *student = [[Student alloc] init];[student studentMethod]方法的过程- (void)studentMethod;方法存在于Student的class内部。
student(实例对象)的isa指针找到Student的class。Student的class内部找到- (void)studentMethod;方法并调用。[student personMethod]方法的过程- (void)personMethod;方法存在于Person的class内部。
student(实例对象)的isa指针找到Student的class。Student的class内部找是否存在- (void)personMethod;方法。Student的class内的superclass找到Person的class。Person的class内找是否存在- (void)personMethod;方法。[student init]方法的过程- (void)init;方法存在于NSObject的class内部。
student(实例对象)的isa指针找到Student的class。Student的class内部找是否存在- (void)init;方法。Student的class内的superclass指针找到Person的class。Person的class内找是否存在- (void)init;方法。Person的class内的superclass指针找到NSObject的meta-class。NSObject的class内找是否存在- (void)init;方法;有如下两个类,继承关系如下 :
Student->Person->NSobject
@interface Person : NSObject
- (void)personMethod;
+ (void)personClassMethod;
@end
@implementation Person
- (void)personMethod {};
+ (void)personClassMethod {};
@end@interface Student : Person
- (void)studentMethod;
+ (void)studentClassMethod;
@end
@implementation Student
- (void)studentMethod {};
+ (void)studentClassMethod {};
@end[Student studentClassMethod];方法的过程+ (void)studentClassMethod;方法存储在Student的meta-class内。
Student类对象的isa找到Student的meta-class。Student的meta-class内找类方法+ (void)studentClassMethod;并调用。[Student personClassMethod];方法的过程+ (void)personClassMethod;方法存储在Person的meta-class内
Student类对象的isa找到Student的meta-class。Student的meta-class中不存在+ (void)personClassMethod;方法。Student的meta-class内的superclass找到Person的meta-class。Person的meta-class方法内找是否存在+ (void)personClassMethod;方法。[Student load];方法的过程+ (void)load;是NSObject的类方法。
Student类对象的isa找到Student的meta-class。Student的meta-class中不存在+ (void)load;方法。Student的meta-class内的superclass找到Person的meta-class。Person的meta-class方法内找是否存在+ (void)load;方法。Person的meta-class内不存在+ (void)load;方法。Person的meta-class内的superclass找到NSObject的meta-class。NSObject的meta-class内找是否存在+ (void)load;方法。
下面是一张广为流传关于isa、superclass的经典图。

instance的isa指向class class的isa指向meta-class meta-class的isa指向基类的meta-classclass的superclass指向父类的class superclass指针为nil meta-class的superclass指向父类的meta-class meta-class的superclass指向基类的classisa找到class,方法不存在,就通过superclass找父类。
isa找meta-class方法不存在,就通过superclass找父类。