Swift 4与Objective-C中实现KVO时是否需要移除观察者?
deinit 中移除观察者? 这是个特别务实的问题——毕竟Objective-C时代“必须手动移除KVO观察者”的规则深入人心,换到Swift里突然没明确说明,确实容易犯嘀咕。我给你把这个事儿掰明白:
Swift 4 引入的现代闭包式KVO,不需要手动移除观察者
苹果在Swift 4里重构了KVO API,使用observe(_:options:changeHandler:)方法会返回一个NSKeyValueObservation对象。这个对象的设计非常巧妙:只要你把它用强引用持有(比如存在实例属性里),当持有它的对象被销毁进入deinit时,NSKeyValueObservation也会被释放,同时自动帮你移除对应的观察关系。举个实际代码例子:
class TemperatureMonitor: NSObject { var thermostat: Thermostat? var temperatureObservation: NSKeyValueObservation? init(thermostat: Thermostat) { self.thermostat = thermostat temperatureObservation = thermostat.observe(\.currentTemp, options: [.new]) { [weak self] _, change in guard let newTemp = change.newValue else { return } self?.handleTemperatureChange(newTemp) } } private func handleTemperatureChange(_ temp: Double) { // 处理温度变化逻辑 } }这里当
TemperatureMonitor实例被销毁时,temperatureObservation会被自动释放,观察关系也随之清除,完全不用在deinit里写额外代码。如果还在使用Objective-C风格的老KVO API,依然需要手动移除
要是你为了兼容旧代码,还是用addObserver:forKeyPath:options:context:这类传统方法,那Objective-C的规则依然生效——必须在deinit里调用removeObserver:forKeyPath:或者removeObserver:forKeyPath:context:,否则可能引发崩溃或内存异常。官方文档为什么没提?
因为官方示例全用的是Swift 4的现代KVO API,这种API已经通过NSKeyValueObservation的生命周期自动处理了移除逻辑,自然不需要额外强调。这也是Swift 4 KVO设计的核心改进之一,就是为了规避Objective-C里“忘记移除观察者”的常见坑。
总结来说:用Swift 4及以后的闭包式KVO API,不用手动移除;用老的Objective-C风格API,就得遵循老规则手动清理。
内容的提问来源于stack exchange,提问作者EGMSSE

