runtime相关面试问题
1:数据结构
id = objc_object {isa_t , 关于isa操作相关,弱引用相关,关联对象相关,内存管理相关 }
class - 》objc_class -〉objc_object
公用体isa_t , 64位
指针型isa, 非指针型isa。
2:对象,类对象,元类对象
类对象储存实例方法列表等信息
元类对象储存类方法列表等信息
superclass和isa 。。。
root
super
sub
3:消息传递:
objc_msgsend( )
objc_msgsendsuper( )
缓存查找(哈希查找),父类查找,根类查找。 都没命中进入消息转发流程。。
4:消息的缓存查找
给定值sel,目标值是对应bucket_t中的IMP。
哈希查找根据给定的key,查找 返回给对象。
5:当前类中查找
已排序好的使用二分查找
没有排序的列表使用一般遍历查找。
6: 父类逐级查找
7:Method-Swizzling
交换方法实现。
class_getInstanceMethod( )
method_exchangeimpwentations( )
8:为一个类 动态添加方法:
performSelector:
class_addmethod( )
9:动态方法解析
@dynamic
动态运行时语言将函数决议推辞到运行时。
编译时语言在编译期进行函数决议。
10:runtime实战
【obj foo】和objc_msgsend()函数之间有什么关系?
objc_msgSend()是[obj foo]的具体实现。
在runtime中,objc_msgSend()是一个c函数,[obj foo]会被翻译成这样的形式objc_msgSend(obj, foo)。
去obj的对应的类中找方法
先找缓存,找不到再去找方法列表,
再找父类,如此向上传递。
最后再找不到就要转发。
11:runtime如何通过selector找到对应的IMP地址的
. 每一个类对象中都一个对象方法列表(对象方法缓存)
. 类方法列表是存放在类对象中isa指针指向的元类对象中(类方法缓存)
. 方法列表中每个方法结构体中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现.
. 当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类对象方法列表里查找
. 当我们发送一个消息给一个类时,这条消息会在类的Meta Class对象的方法列表里查找
Selector、Method 和 IMP 的关系可以这样描述:在运行期分发消息,方法列表中的每一个实体都是一个方法(Method),它的名字叫做选择器(SEL),对应着一种方法实现(IMP)。
/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;
struct objc_method {
SEL method_name; // 方法选择器。
char *method_types; // 存储着方法的参数类型和返回值类型。
IMP method_imp; // 函数指针。
}