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

如何通过NSObject.KeyValueObservingPublisher获取新旧值?

解决Combine KVO获取属性新旧值的问题

你当前的代码只能拿到初始值和新值,是因为publisher(for: \.name, options: ...)默认仅输出属性的当前值。要同时获取新旧值,可通过以下两种可靠方法实现:

方法一:利用KVO原生变更信息

使用NSObject的publisher(forKeyPath:options:)方法,它会输出包含完整变更详情的NSKeyValueObservedChange对象,从中可直接提取新旧值:

import Combine

class Person: NSObject {
    @objc dynamic var name: String
    
    init(name: String) {
        self.name = name
    }
}

let person = Person(name: "John")
var cancellables = Set<AnyCancellable>()

person.publisher(forKeyPath: \Person.name, options: [.initial, .new, .old])
    .sink(receiveCompletion: { _ in }, receiveValue: { change in
        if let initialValue = change.initialValue {
            print("初始值: \(initialValue)")
        }
        if let oldValue = change.oldValue, let newValue = change.newValue {
            print("旧值: \(oldValue), 新值: \(newValue)")
        }
    })
    .store(in: &cancellables)

person.name = "Allen"

输出结果:

初始值: John
旧值: John, 新值: Allen

方法二:用Combine操作符跟踪前值

通过scan操作符存储上一次的属性值,将当前值与前值组合成元组输出,纯Combine风格实现:

import Combine

class Person: NSObject {
    @objc dynamic var name: String
    
    init(name: String) {
        self.name = name
    }
}

let person = Person(name: "John")
var cancellables = Set<AnyCancellable>()

person.publisher(for: \.name, options: [.initial, .new])
    .scan((old: nil as String?, new: nil as String?)) { previous, current in
        (old: previous.new, new: current)
    }
    .filter { $0.new != nil }
    .sink { pair in
        if let initial = pair.new, pair.old == nil {
            print("初始值: \(initial)")
        } else if let old = pair.old, let new = pair.new {
            print("旧值: \(old), 新值: \(new)")
        }
    }
    .store(in: &cancellables)

person.name = "Allen"

输出结果:

初始值: John
旧值: John, 新值: Allen

关键说明

  • 方法一直接复用KVO原生变更数据,适合需要完整KVO细节的场景;
  • 方法二完全基于Combine操作符实现,更贴合响应式编程风格;
  • 务必将订阅者存入Set<AnyCancellable>,避免订阅因对象提前释放失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:22:37