对象的isa指向哪里?
类信息存放在哪里?
Objective-C对象,简称OC对象,分为三类:
-
instance
对象(实例对象) -
class
对象(类对象) -
meta-class
对象(元类对象)
instance
对象就是通过类alloc出来的对象,每次alloc都会产生新的instance
对象,占据不同的内存
instance
对象在内存中存储的信息有哪些?
- isa指针
- 成员变量
每个类在内存中有且只有一份对象。
class
对象在内存中存储的信息有哪些?
- isa指针
- superclass指针
- 类的属性信息(@property)、类的对象方法信息(instance_method)、类的成员变量信息(ivar)、类的协议信息(protocol)
每个类在内存中有且只有一份meta-class对象。
meta-class对象和class对象的内存结构中是一样的只是用途不一样,在内存中存储的信息包括:
- isa指针
- superclass指针
- 类的类方法信息(class method)
- ......
调用对象方法和类方法的过程
对象方法调用过程
-
instance
的isa指向class - 当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用
类方法调用过程
-
class
的isa指向meta-class
- 当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
superclass的调用过程
@interface Person : NSObject
@interface Student : Person
当Student的instance对象要调用Person中的对象方法时,会先通过isa指针找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用。
当Student的class要调用Person中的类方法时,会先通过isa指针找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用。
- instance的isa指向class
- class的isa指向meta-class
- meta-class的isa指向基类的meta-class
- class的superclass指向父类的isa
- 如果没有父类,superclass指向nil
- meta-class的superclass指向父类的meta-class
- 基类的meta-class的superclass指向基类的class
看两个函数
OBJC_EXPORT BOOL class_isMetaClass(Class cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
OBJC_EXPORT Class object_getClass(id obj)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
class_isMetaClass
用于判断Class
对象是否为元类,object_getClass
用于获取对象的isa指针指向的对象。
再看如下代码:
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
//输出1
NSLog(@"%d", [p class] == object_getClass(p));
//输出0
NSLog(@"%d", class_isMetaClass(object_getClass(p)));
//输出1
NSLog(@"%d", class_isMetaClass(object_getClass([Person class])));
//输出0
NSLog(@"%d", object_getClass(p) == object_getClass([Person class]));
}
return 0;
}
通过代码可以看出,一个实例对象通过class方法获取的Class就是它的isa指针指向的类对象,而类对象不是元类,类对象的isa指针指向的对象是元类。
思考题
@interface Person : NSObject
+ (void)test;
@end
@implementation Person
@end
@interface NSObject (Test)
+ (void)test;
@end
@implementation NSObject (Test)
-(void)test{
NSLog(@"NSObject+Test");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
[Person test];
[NSObject test];
}
return 0;
}
以上代码能运行成功吗?
答案:能运行成功,从isa,superclass去考虑(通过objc_msgSend查找方法时,不知道是实例方法还是类方法)