参考源码
runtime
的源码:https://opensource.apple.com/tarballs/objc4/
对象分类
Objective-C
对象简称 OC
对象,可以分为 3
种类型。
instance
对象:实例对象。
class
对象:类对象。
meta-class
对象:元类对象。
instance实例对象
实例对象就是通过类 alloc
出来的对象,一个类可以实例化很多对象,每个对象都占据不同的内存空间。
每个对象都有一个 isa
指针,因为所有的 OC 类都继承自 NSObject
类,而 NSObject
类中有一个 isa
指针。又因为 isa
指针是对象中第一个成员变量,所以 isa
的地址,同时也是对象的地址。
实例对象在内存中存储的信息主要包括:
isa
指针,指向类对象。
成员变量
。
class类对象
一个类的类对象是唯一的,可以通过多种方式获得,并且 OC
对象的 isa
指针指向的就是这个类的类对象。
// 实例对象
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
// 获取类对象方式1
Class objClass1 = [obj1 class];
Class objClass2 = [obj2 class];
// 获取类对象方式2
Class objClass3 = object_getClass(obj1);
// 获取类对象方式3
Class objClass4 = [NSObject class];
// 无论调用多少次class,返回的都是同一个类对象
Class objClass4 = [[[NSObject class] class] class];
NSLog(@"%@", (objClass1 == objClass2 && objClass1 == objClass3 && objClass1 == objClass4) ? @"相等" : @"不相等"); // 相等
通过 object_getClass
函数实现可以看出 OC
对象的 isa
指针指向的确实是类对象:
struct objc_object {
Class getIsa();
};
typedef struct objc_object *id;
// 如果obj是实例对象,则返回类对象
// 如果obj是类对象,则返回元类对象
// 如果obj是元类对象,则返回基类(NSObject)的元类对象
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
还有一个类似的函数,传入一个字符串类名,返回一个类对象(只能返回类对象,但是可以通过类对象获取元类对象):
Class objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
类对象内存中存储的信息主要包括:
isa
指针,指向元类对象。
superclass
指针,指向父类的类对象,如果没有父类(NSObject
没父类)则为nil
。类的
属性
信息(@property
)、类的对象方法
信息(instance method
)。类都
协议
信息(@protocol
)、类的成员变量
信息(ivar
)。
元类对象
一个类的元类对象也是唯一的,通过 runtime
的 object_getClass
函数,把类对象作为参数传入就可以获取到元类对象:
Class metaClass1 = object_getClass([NSObject class]);
// 判断是类对象还是元类对象
BOOL isMetaClass = class_isMetaClass(metaClass1);
元类对象和类对象的 内存结构
是完全一样的,但是用途不一样。元类对象内存中存储的信息主要包括:
isa
指针,指向基类(NSObject
)的元类对象。
superclass
指针,指向父类的元类对象,如果没有父类(NSObject
没父类)则指向类对象。类的
类方法
信息(class method
)。