一个OC对象的旅程
导语:一个初级iOS开发者一定很好奇一个OC对象创建出来到底是怎么样的,今天我们就来简单看一下(如果有误请留言指正,非常感谢)
- 一个对象创建出来,在底层关系走向如下:
例如: FRPerson继承自NSObject
FRPerson *person = [[FRPerson alloc] init];
一个对象的旅程 |
---|
person是一个局部变量(内存在栈中) |
person变量是一个指针,指向person实例(instance)对象(内存在堆里) |
person实例对象里有isa指针,指向FRPerson类(class)对象(内存在全局区) |
FRPerson类对象(class)里也有isa指针,指向元类(meta-class)对象(内存在全局区) |
FRPerson元类对象的isa指向基类元类类对象(NSObject的元类对象)(内存在全局区) |
基类的元类对象的isa指针指向自己 |
实例对象可以创建多个,创建一个就会通过alloc在堆里申请一份新的内存
类对象,元类对象在内存中分别只有一份,获取多少次都是同一个地址
实例对象 类对象 元类对象
-
具体内存结构
-
实例对象(instance)
instance |
---|
isa指针(前8个字节) |
成员变量的值 |
... |
- 类对象 (class)
class |
---|
isa指针(前8个字节) |
superclass指针(8个字节) |
属性信息 |
对象方法信息 |
协议信息 |
成员变量信息 |
... |
- 元类对象(meta-class)
meta-class |
---|
isa指针(前8个字节) |
superclass指针(8个字节) |
类方法信息 |
... |
- 获取 实例对象 类对象 元类对象
导入头文件
#import <objc/runtime.h>
//实例对象
Person *person = [[Person alloc] init];
//类对象
Class personClass = [person class];
//元类对象
Class metaClass = object_getClass(personClass);
BOOL isMetaClass = class_isMetaClass(metaClass);
NSLog(@"%p,%p,%p,%d",person,personClass,metaClass,isMetaClass);
//0x100494140,0x100008100,0x1000080d8,1
object_getClass函数参数如果传入的是实例对象,返回的就是类对象,传入类对象返回的就是元类对象
类对象和元类对象都是Class类型,也就是说他们的类型是一样的,只是里面存储的信息不同
class_isMetaClass判断是否是一个元类对象
superclass指针
superclass指针 |
---|
类对象的superclass指针指向父类的类对象,一直到基类,基类的superclass为nil |
元类对象的superclass 指向父类的元类对象,一直到基类元类对象,但是基类元类对象的superclass会指向基类的类对象 |
注意:根据superclass指针最终走向,如果一个类调用一个类方法,一直找不到,最终会找到基类的类对象中,而基类类对象保存的方法是基类的对象方法,如果有个同名的对象方法,系统会调用这个方法。(结果就是一个类调用了对象方法)
从中得出一个推论:runtime运行时是不会根据是对象方法,类方法来调用方法的;对象方法,类方法只是确定他们的存放位置。
网上找到的一个关系图,非常的形象:
- 下一篇,我们说一下方法是怎么调用的。 浅谈系列-OC方法调用到底是个什么流程