该文章属笔者原创, 未经允许, 禁止转载
OC中的类
- instance 实例类
- class 类
- meta-class 元类
类的底层实现是struct, 比如NSObject实例类型的实现:
struct NSObject_IMPL {
Class isa
}
继承自NSObject的HLPerson实例类型
struct HLPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _age;
}
查看对象所占空间, 常用的几个命令
-
runtime
中的class_getInstanceSize([NSObject class])
, 创建一个实例对象, 至少需要多少内存空间 -
<malloc/malloc.h>
中的malloc_size((__bridge const void *)obj)
, 创建一个实例对象,实际上分配了多少内存
各种类的结构
- instance:
isa指针
其他成员变量(值)
- class: 可以通过
class
/objc_class
/object_class
方法获取isa指针
superclass指针
属性信息(@proprety)
对象方法信息
协议信息
成员变量信息(ivar)
- meta-class: 通过
object_class
方法获取, 传入的对象必须是class
类isa指针
superclass指针
类方法信息
instance中不存放方法信息, 对象方法(减号方法)存放在class中, 类方法(加号方法)存放在meta-class中
方法调用
OC
中的方法调用, 实质是发消息, 使用的是objc_msgSend(receiver, selector, arg1, arg2, ...)
可以看出, 其实, 底层在调用方法的时候, 其他是不知道是加号方法
还是减号方法
的, 因为他只接收了一个方法对象
和一个方法名称
OC
中的方法调用跟isa指针
和superclass指针
息息相关
-
调用实例方法
- 通过
instance
的isa指针
找到这个类的Class类
,Class类
中存放着实例方法, 如果没找到, 进行下一步 - 通过
Class类
的superclass
指针, 找到Class类
的父类, 也是一个Class类
, 依次向上查找 - 直到
Root Class
都没有找到的话, 由于Root Class
的superclass
指向nil
, 这时候就会报错说不识别方法
- 通过
-
调用类方法
- 通过
instance
的isa指针
找到这个类的Class类
, 再根据Class类
的isa指针
找到该类的meta-class类
, 这里存放着类方法, 若没找到, 进入下一步 - 通过
meta-class类
的superclass指针
, 找到meta-class类
的父类, 也是一个meta-class类
, 依次向上查找 - 直到
Root meta-class
都没有找到的话, 由于Root meta-class
的superclass
指向Root Class
, 再在这里找一次方法, 如果没有找到, 这时候就会报错说不识别方法
- 通过
调用实例方法
和调用类方法
的差别在于第3步
类方法的调用会多查找一步, 那就是找到Root meta-class
对应的Root Class
, 这时候, 如果在Root Class
中实现一个同名的对象方法(减号方法)
, 同样会调用成功, 这就是之前为什么说, 在发消息的时候, 底层不知道是实例方法还是类方法