浅谈系列-OC对象创建出来到底是怎么样的呢

928 阅读3分钟

一个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运行时是不会根据是对象方法,类方法来调用方法的;对象方法,类方法只是确定他们的存放位置。

网上找到的一个关系图,非常的形象:

isa指针.png