MST

星途 面试题库

面试题:Objective-C中KVO机制在iOS开发的深度应用

描述Objective-C的KVO(Key - Value Observing)机制在iOS开发中的工作原理。请举例说明如何使用KVO来监听视图控制器中某个属性的变化,并处理相关逻辑,同时阐述KVO可能存在的内存问题及解决方案。
25.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

KVO工作原理

  1. 注册观察:在观察者对象中,通过addObserver:forKeyPath:options:context:方法为被观察对象的特定属性注册观察。此方法会告知系统,当被观察对象指定属性值发生改变时,要通知观察者。
  2. 底层实现:当被观察对象的属性值改变时,系统会自动调用观察者的observeValueForKeyPath:ofObject:change:context:方法。实际上,系统在注册观察时,会动态创建被观察对象的子类,并在子类中重写被观察属性的setter方法。当属性值改变时,就会触发通知。
  3. 通知处理:观察者在observeValueForKeyPath:ofObject:change:context:方法中,根据传入的参数来判断是哪个对象的哪个属性发生了变化,并执行相应的处理逻辑。

举例监听视图控制器属性变化

假设在一个视图控制器ViewController中有一个name属性,需要监听它的变化。

  1. 定义视图控制器及属性
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *name;

@end
  1. 注册观察 在视图控制器的viewDidLoad方法中注册观察:
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    self.name = @"初始值";
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"name"]) {
        NSString *newName = change[NSKeyValueChangeNewKey];
        NSLog(@"名字变为: %@", newName);
    }
}

- (void)dealloc {
    [self removeObserver:self forKeyPath:@"name"];
}

@end
  1. 改变属性值触发监听 在其他地方改变name属性值时,observeValueForKeyPath:ofObject:change:context:方法就会被调用。

KVO内存问题及解决方案

  1. 内存问题:如果观察者对象先于被观察对象释放,而没有及时移除观察,就会导致野指针错误,程序崩溃。例如,视图控制器A观察视图控制器B的某个属性,当A被释放时,如果没有移除对B属性的观察,B再改变属性值时,就会向已释放的A发送通知,造成崩溃。
  2. 解决方案:在观察者对象的dealloc方法中,调用removeObserver:forKeyPath:方法移除对被观察对象属性的观察。如上述代码中在ViewControllerdealloc方法里移除对name属性的观察。同时,要确保在整个生命周期内,观察的注册和移除是平衡的,避免重复注册或遗漏移除。