iOS UIKit MVC下Swift中一个模型如何通知另一个模型属性变更?
iOS模型间属性监听的常用实现方案
你提到的KVO和NotificationCenter并不局限于模型和控制器间通信,完全可以用于模型层内部的属性变更通知,针对你的场景,常用的实现方案如下:
1. 自定义闭包回调(最轻量化)
适合仅存在少量观察者的场景,无额外框架依赖,代码逻辑直观
class ModelA { static let shared = ModelA() // 若需要支持多个观察者,可改为数组存储多组回调 var onFooUpdate: ((CustomObjectClassName) -> Void)? private(set) var foo: CustomObjectClassName { didSet { // foo变更时触发回调 onFooUpdate?(foo) } } } class ModelB { private var bar: ModelC init() { self.bar = ModelC(ModelA.shared.foo) // 注册监听foo变更 ModelA.shared.onFooUpdate = { [weak self] newFoo in guard let self = self else { return } self.bar = ModelC(newFoo) } } }
2. KVO(键值观察)
适合需要兼容Objective-C代码、或者已有KVO使用规范的项目,要求被监听类继承NSObject
import Foundation // ModelA需要继承NSObject,监听属性加@objc dynamic修饰 class ModelA: NSObject { static let shared = ModelA() @objc dynamic private(set) var foo: CustomObjectClassName } class ModelB { private var bar: ModelC // 存储KVO观测实例,否则会被提前释放导致监听失效 private var fooObservation: NSKeyValueObservation? init() { self.bar = ModelC(ModelA.shared.foo) // 初始化KVO监听 fooObservation = ModelA.shared.observe(\.foo, options: [.new]) { [weak self] _, change in guard let self = self, let newFoo = change.newValue else { return } self.bar = ModelC(newFoo) } } }
3. NotificationCenter(通知中心)
适合存在多个不同类型对象需要监听foo变更的广播场景,耦合度更低
// 先全局定义通知名称 extension NSNotification.Name { static let modelAFooDidUpdate = NSNotification.Name("ModelAFooDidUpdateNotification") } class ModelA { static let shared = ModelA() private(set) var foo: CustomObjectClassName { didSet { // foo变更时广播通知 NotificationCenter.default.post(name: .modelAFooDidUpdate, object: foo) } } } class ModelB { private var bar: ModelC init() { self.bar = ModelC(ModelA.shared.foo) // 注册通知监听 NotificationCenter.default.addObserver(self, selector: #selector(handleFooUpdate(_:)), name: .modelAFooDidUpdate, object: nil) } @objc private func handleFooUpdate(_ notification: Notification) { guard let newFoo = notification.object as? CustomObjectClassName else { return } self.bar = ModelC(newFoo) } deinit { // 移除观察者,iOS9+系统会自动处理,但显式移除更稳妥 NotificationCenter.default.removeObserver(self) } }
4. Combine框架(iOS 13+支持)
适合现代Swift项目,响应式编程场景,代码更简洁易维护
import Combine class ModelA { static let shared = ModelA() // 用@Published修饰属性,自动发布变更事件 @Published private(set) var foo: CustomObjectClassName } class ModelB { private var bar: ModelC // 存储订阅实例,否则会被自动取消 private var cancellable: AnyCancellable? init() { self.bar = ModelC(ModelA.shared.foo) // 订阅foo的变更事件 cancellable = ModelA.shared.$foo .sink { [weak self] newFoo in guard let self = self else { return } self.bar = ModelC(newFoo) } } }
方案选择建议
- 若项目最低支持iOS13,优先选Combine,写法简洁安全,是苹果官方推荐的现代响应式方案
- 若需要兼容旧版本,且只有1-2个观察者,选自定义闭包回调,无额外依赖性能最好
- 若有多个不同模块的对象都需要监听foo变更,选NotificationCenter
- 若项目本身有大量ObjC兼容代码,已经在用KVO规范,继续用KVO即可
内容的提问来源于stack exchange,提问作者XYZ
相关产品推荐
相关产品推荐

