MST

星途 面试题库

面试题:Objective-C中KVO的实现机制及局限性

详细阐述Objective-C中KVO的实现原理,包括系统如何动态生成子类以及重写setter方法等机制。同时,说明KVO在使用过程中有哪些局限性。
30.2万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

KVO实现原理

  1. 动态生成子类
    • 当一个对象(假设为subject)被观察时,运行时系统会动态创建该对象类的一个子类。例如,如果被观察对象是NSObject的某个子类MyClass,系统会创建一个MyClass的子类,命名可能类似NSKVONotifying_MyClass
    • 这个动态生成的子类继承自原始类,拥有原始类的所有属性和方法。
  2. 重写setter方法
    • 对于被观察的属性,动态生成的子类会重写其对应的setter方法。例如,对于属性name,原始类可能有- (void)setName:(NSString *)name方法。在动态子类中,这个方法会被重写。
    • 在重写的setter方法中,首先会调用父类(即原始类)的setter方法来实际设置属性的值。然后,它会通知观察者属性值发生了变化。通知过程是通过NSNotificationCenter来实现的,系统会发布一个NSKeyValueChangeNotification通知,包含了属性变化的相关信息,如变化的类型(新值、旧值等)。
  3. isa混写
    • 系统会将被观察对象的isa指针指向动态生成的子类。这样,当调用被观察对象的setter方法时,实际上调用的是动态子类重写后的setter方法,从而实现属性变化的通知。

KVO使用的局限性

  1. 仅适用于属性变化
    • KVO只能观察属性值的变化,对于对象内部其他状态的改变(如方法调用导致的内部逻辑变化,但属性值未改变)无法进行观察。例如,一个对象的某个方法执行了复杂的计算,但没有改变任何可观察属性,KVO无法感知这种变化。
  2. 依赖于KVC
    • KVO是基于KVC(Key - Value Coding)实现的,这意味着它要求被观察的属性遵循KVC的命名和访问规则。如果属性的访问方法不符合KVC规范,KVO可能无法正常工作。
  3. 性能开销
    • 动态生成子类以及重写setter方法等操作会带来一定的性能开销。特别是在有大量对象被观察的情况下,内存和CPU的消耗会比较明显。
  4. 难以调试
    • 由于KVO是在运行时动态生成子类和重写方法,调试过程相对复杂。当出现问题时,很难直接定位到是KVO机制本身的问题还是其他代码的问题,因为动态生成的子类和相关逻辑在代码中不是显式可见的。
  5. 循环引用问题
    • 如果观察者和被观察对象之间形成循环引用,可能会导致内存泄漏。例如,一个对象A观察对象B,而对象B又持有对象A的引用,这种情况下如果不妥善处理,会造成内存无法释放。