2019|2019 iOS 面试 -中级篇之 Runtime

1. objc在向一个对象发送消息时,发生了什么? 根据对象的isa指针找到该对象所属的类,去obj的对应的类中找方法

  • 1.首先,在相应操作的对象中的缓存方法列表中找调用的方法,如果找到,转向相应实现并执行。
  • 2.如果没找到,在相应操作的对象中的方法列表中找调用的方法,如果找到,转向相应实现执行
  • 3.如果没找到,去父类指针所指向的对象中执行1,2.
  • 4.以此类推,如果一直到根类还没找到,转向拦截调用,走消息转发机制。
  • 5.如果没有重写拦截调用的方法,程序报错。
如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。也不会崩溃。
参考:ios objc向一个对象发送消息时,发生了什么?
2. 什么时候会报unrecognized selector错误?iOS有哪些机制来避免走到这一步?
  • 对象未实现该方法。
  • 对象已经被释放。
避免:
  • 使用[id respondsToSelector:]进行判断。
    参考:什么时候会报unrecognized selector错误?
3. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
  • 不能向编译后得到的类增加实例变量
  • 能向运行时创建的类中添加实例变量
解释:
  • 1.编译后的类已经注册在runtime中,类结构体中的objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定,runtime会调用class_setvarlayout或class_setWeaklvarLayout来处理strong weak引用.所以不能向存在的类中添加实例变量
  • 2.运行时创建的类是可以添加实例变量,调用class_addIvar函数.但是的在调objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.
参考:能否向编译后得到的类中增加实例变量?
4. runtime如何实现weak变量的自动置nil? 首先要搞清楚weak属性的特点:
  • weak策略表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似; 然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)
    那么runtime如何实现weak变量的自动置nil?
  • runtime对注册的类,会进行布局,会将 weak 对象放入一个 hash 表中。用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会调用对象的 dealloc 方法,假设 weak 指向的对象内存地址是a,那么就会以a为key,在这个 weak hash表中搜索,找到所有以a为key的 weak 对象,从而设置为 nil。
    weak属性需要在dealloc中置nil么?
  • 在ARC环境无论是强指针还是弱指针都无需在 dealloc 设置为 nil , ARC 会自动帮我们处理,即便是编译器不帮我们做这些,weak也不需要在dealloc中置nil,在属性所指的对象遭到摧毁时,属性值也会清空
模拟下weak的setter方法,大致如下
- (void)setObject:(NSObject *)object{ objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN); [object cyl_runAtDealloc:^{ _object = nil; }]; }

参考链接:runtime 相关试题解答
5. 给类添加一个属性后,在类结构体里哪些元素会发生变化?
  • instance_size :实例的内存大小
  • objc_ivar_list *ivars:属性列表
参考链接:靠谱的 iOS 面试题
相关阅读:
【2019|2019 iOS 面试 -中级篇之 Runtime】1、iOS 面试题 --- 基础部分
2、iOS 面试题 --- 中级篇 Block
3、iOS 面试题 --- 中级篇 Runloop
4、iOS 面试题 --- 高级篇

    推荐阅读