runtime是oc的一种代码运行机制,我们程序中执行的代码最终都会以c语言的形式执行,例如:[target doSomething] 在运行中会被转换成 objc_msgSend(target,@selector(doSomething));
对象在runtime中都以结构体的形式体现
struct objc_class {
Class isa;//指针,顾名思义,表示是一个什么,
//实例的isa指向类对象,类对象的isa指向元类
#if !__OBJC2__
Class super_class; //指向父类
const char *name; //类名
long version;
long info;
long instance_size
struct objc_ivar_list *ivars //成员变量列表
struct objc_method_list **methodLists; //方法列表
struct objc_cache *cache;//缓存
//一种优化,调用过的方法存入缓存列表,下次调用先找缓存
struct objc_protocol_list *protocols //协议列表
#endif
} OBJC2_UNAVAILABLE;
下面我们通过oc中方法的调用来了解一下runtime的过程
如果用实例对象调用实例方法,会到实例的isa指针指向的对象(也就是类对象)操作
如果调用的是类方法,就会到类对象的isa指针指向的对象(也就是元类对象)中操作
- 首先,在相应操作的对象中的缓存方法列表中找打调用的方法,如果找到,转向相应的实现并执行。
- 如果没找到,在相应操作的对象中的方法列表中找调用的方法,如果找到,转向相应实现并执行。
- 如果没找到,去父类指针所指向的对象中执行1 2
- 以此类推,如果一直到根类还没找到,转向拦截调用。
- 如果没有重写拦截调用方法,程序报错。
也就是说如果继承重写父类的方法,并不会将父类方法覆盖,只是在当前子类找到了该方法,不再继续找了。
用runtime可以做什么?
一般的开发中用不到,只有一些特殊场景,比如通过objc_setAssociatedObject
扩展对象的属性,而又不使用继承方案,或使用method_exchangeImplementations
来执行自己的方法,而不执行系统类的方法。
基本参考这里;
网友评论