6、面试整理-Runtime面试题整理
1、OC是动态运行时语言是什么意思?
- 动态类型:运行时确定对象的类型,编译时期能通过,但不代表运行过程中没有问题
- 动态绑定:运行时才确定对象调用的方法(消息转发)
- 动态加载:动态库的方法实现不拷贝到程序中,只记录引用,直到使用相关方法的时候才到库里面查找方法实现
2、runtime能做什么?
- 获取类的成员变量、方法、协议
- 为类添加成员变量、方法、协议
- 动态改变方法实现
3、class_copyIvarList与class_copyPropertyList的区别?
- 1、
class_copyIvarList可以获取.h和.m中的所有属性以及@interface大括号中声明的变量,获取的属性名称有下划线(大括号中的除外)。
- 2、
class_copyPropertyList只能获取由@property声明的属性(包括.m),获取的属性名称不带下划线。
4、class_ro_t和class_rw_t的区别?
class_rw_t提供了运行时对类拓展的能力,class_rw_t结构体中存储了class_ro_t。
class_ro_t存储的是类在编译时已经确定的信息,是不可改变的。
- 二者都存有类的方法、属性(成员变量)、协议等信息,不过存储它们的列表实现方式不同。简单的说
class_rw_t存储列表使用的二维数组,class_ro_t使用的一维数组。
- 运行时修改类的方法,属性,协议等都存储于
class_rw_t中
5、什么是 Method Swizzle(黑魔法),什么情况下会使用?
Method Swizzle 是改变一个已存在的选择器(SEL)对应的实现(IMP)的过程。
- 类的方法列表存放着
SEL的名字和IMP的映射关系。
- 开发者可以利用
method_exchangeImplementations 来交换2个方法中的IMP
- 开发者可以利用
method_setImplementation 来直接设置某个方法的IMP
- 这就可以在运行时改变
SEL和IMP的映射关系,从而实现方法替换。
6、Method Swizzle注意事项
- 为了确保
Swizzle Method方法替换一定被执行调用,可以在load中执行
+load里面使用的时候不要调用[super load]。如果多次调用了[super load],可能会出现“Swizzle无效”的假象
- 避免调用
[super load]导致Swizzling多次执行,在load中使用dispatch_once确保交换只被执行一次。
- 子类替换没有实现的继承方法,会替换掉父类中的实现,影响父类及其他子嘞
+initialize 里面使用要加dispatch_once
- 进行版本迭代的时候需要进行一些检验,防止系统库的函数发生了变化
7、如何hook一个对象的方法,而不影响其它对象?
- 方法1:新建一个子类重写方法
- 方法2:让这个对象的类遵循某个协议,
hook时判断。弊端是其他对象遵循了这个协议会受到影响。
- 方法3:运行时创建一个新的子类,修改对象
isa 指针指向子类,hook 时使用isKindOf 判断类型