You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4 KVO新语法observe使用问题求助

搞定Swift 4 KVO的那些坑——帮你排查代码问题

嘿,我看了你的代码,这里面有几个Swift 4 KVO常见的错误点,我帮你一一梳理:


1. 被观察的属性没满足KVO的必要条件

Swift 4对KVO的要求比之前严格,被观察的属性必须同时加上@objc和dynamic修饰符,而且所属的类必须继承自NSObject。你代码里的MyObjectToObserve和它的myDate属性得这么写才行:

class MyObjectToObserve: NSObject {
    @objc dynamic var myDate: Date
    
    init(date: Date) {
        self.myDate = date
        super.init()
    }
}

要是没加这两个标记,KVO会悄无声息地失效,连编译报错都没有,这绝对是最容易踩的坑!

2. observe方法的调用对象错了

你现在是在MyObserver自己身上调用observe(\.objectToObserve.myDate),但我们要观察的是objectToObserve里的myDate变化,正确的做法应该是直接在objectToObserve这个目标对象上调用observe方法,修改后的代码应该是这样:

class MyObserver: NSObject {
    @objc var objectToObserve: MyObjectToObserve
    var observation: NSKeyValueObservation?
    
    init(object: MyObjectToObserve) {
        objectToObserve = object
        super.init()
        // 这里改成在objectToObserve上调用observe,观察它的myDate属性
        observation = objectToObserve.observe(\.myDate) { [weak self] observedObj, change in
            // 用weak self避免循环引用,这也是内存管理的关键点
            guard let self = self else { return }
            // 这里写你的处理逻辑,比如打印变化
            print("日期更新了:\(observedObj.myDate)")
        }
    }
}

原来的写法相当于观察MyObserver实例的objectToObserve.myDate路径,但objectToObserve本身如果不是dynamic属性,这个路径的KVO根本不会生效,逻辑上也完全不对。

3. 额外注意:内存管理与初始化顺序

初始化顺序这块你没问题,先给objectToObserve赋值再调用super.init()是正确的。不过要注意闭包的捕获,一定要加[weak self],不然MyObserver和objectToObserve会互相持有,导致内存泄漏。另外,NSKeyValueObservation只要你持有它,观察就会持续;一旦observation被释放,观察就自动停止,所以你把它存在MyObserver的属性里是正确的做法。


调整完这几点,你的KVO应该就能正常工作啦!

内容的提问来源于stack exchange,提问作者Eden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:03:12