OC对象的分类

/ 0

参考源码

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)。

元类对象

一个类的元类对象也是唯一的,通过 runtimeobject_getClass 函数,把类对象作为参数传入就可以获取到元类对象:

Class metaClass1 = object_getClass([NSObject class]);

// 判断是类对象还是元类对象
BOOL isMetaClass = class_isMetaClass(metaClass1);

元类对象和类对象的 内存结构 是完全一样的,但是用途不一样。元类对象内存中存储的信息主要包括:

isa 指针,指向基类(NSObject)的元类对象。

superclass 指针,指向父类的元类对象,如果没有父类(NSObject没父类)则指向类对象。

类的 类方法 信息(class method)。