OC 对象的分类

362 阅读3分钟

1. 简单概述

万物皆对象,OC 对象可以分为以下三类:
1、instance 对象 - 实例对象:
  存放 isa、成员变量值;
2、class 对象 - 类对象;
  存放 isa 指针、superclass 指针、类的属性信息(名称)、对象方法、协议、成员变量等;
3、meta-class 对象 - 元类对象;
  isa 指正、类方法等。

2. instance对象(实例对象)

instance 对象就是通过类 alloc 出来的对象,每次调用 alloc 都会产生新的 instance 对象:

Person *person1 = [[Person alloc] init];
Person *person2 = [[Person alloc] init];

person1、person2 是 Person 的 instance 对象(实例对象) 是两个不同的对象。

instance 对象在内存中存储的信息包括:

  • isa 指针;

  • 其他成员变量。

3. class对象 (类对象)

一个类的类对象可以通过以下方式获取:

Person *person1 = [[Person alloc] init];
Person *person2 = [[Person alloc] init];

// Person 对象方法
Class class1= [person1 class];
Class class2= [person2 class];

// Person 类方法
Class class3= [Person class];

// Runtime 方法:参数 -> 实例对象
Class class4= object_getClass(person1);
Class class5= object_getClass(person2);

NSLog(@"class1: %p", class1);
NSLog(@"class2: %p", class2);
NSLog(@"class3: %p", class3);
NSLog(@"class4: %p", class4);
NSLog(@"class5: %p", class5);

日志输出:

OC 对象的分类_Test01[97653:2509948] class1: 0x100001248
OC 对象的分类_Test01[97653:2509948] class2: 0x100001248
OC 对象的分类_Test01[97653:2509948] class3: 0x100001248
OC 对象的分类_Test01[97653:2509948] class4: 0x100001248
OC 对象的分类_Test01[97653:2509948] class5: 0x100001248

上述 5 个类对象地址均相同,它们是同一个对象。
所以:每个类在内存中有且只有一个类对象

类对象在内存中存储的信息主要包括

  • isa 指针
  • superclass 指针
  • 类的属性信息(@property)
  • 类的对象方法信息(instance method)
  • 类的协议信息(protocol)
  • 类的成员变量信息(ivar) - 类型之类的,不存放具体值。

上述方法分析: class 方法: 实例对象方法:- (Class)class

- (Class)class {
    return object_getClass(self);
}

通过调用object_getClass()方法,object_getClass()函数:

Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

返回 isa 指针所指向的对象(实例对象的 isa 指向类对象;class 对象的 isa 指向元类对象;元类对象的 isa 指向 基类的元类对象);

类对象方法:+ (Class)class

+ (Class)class {
    return self;
}

直接返回 self;

4. meta-class对象(元类对象)

元类对象可以通过 runtime 的 object_getClass(),参数传入类对象(如果传实例对象的话得到的是类对象)

Class meta_class= object_getClass([Person class]);
NSLog(@"meta_class: %p", meta_class);

画外音:还有一个名字同 object_getClass 很像的函数 objc_getClass,该方法的注释大概意思:根据传入字符串,返回一个对应名称的类(即:类对象)。

/***********************************************************************
* objc_getClass.  Return the id of the named class.  If the class does
* not exist, call _objc_classLoader and then objc_classHandler, either of 
* which may create a new class.
* Warning: doesn't work if aClassName is the name of a posed-for class's isa!
**********************************************************************/
Class objc_getClass(const char *aClassName)
{
    if (!aClassName) return Nil;

    // NO unconnected, YES class handler
    return look_up_class(aClassName, NO, YES);
}

元类对象也是类对象,所以其内存结构也是一样的,用途不一样而已:
每个类在内存中有且只有一个 meta-class 对象; meta-class对象,在内存中存储的信息主要包括

  • isa指针
  • superclass指针
  • 类的类方法信息(class method)
  • ......

Runtime API 中还提供了一个判断是否为元类对象的方法 class_isMetaClass

Class meta_class= object_getClass([Person class]);
BOOL isMeta_class = class_isMetaClass(meta_class);
NSLog(@"isMeta_class: %d", isMeta_class);

输出:
isMeta_class: 1