Combine与NotificationCenter结合时通知无法接收的问题求助
问题分析与解决方案
这个问题我之前踩过坑!核心原因是你没有持有Combine订阅返回的AnyCancellable对象——一旦代码执行完当前作用域,这些订阅实例就会被立即销毁,自然收不到后续的通知。而旧版的addObserver方式是把观察者注册到NotificationCenter,只要self还存活就能正常收到通知,所以不受影响。
为什么Playground里能正常运行?
Playground的执行环境比较特殊,临时创建的对象生命周期会被自动延长,那些没被持有的AnyCancellable不会马上被释放,所以能收到通知。但在真实iOS项目中,作用域结束后这些对象就会被ARC回收,订阅也就随之取消了。
修复代码示例
只需要在你的类中添加一个属性来存储订阅对象即可,推荐用Set<AnyCancellable>来管理多个订阅:
// 假设你的代码在一个ViewController或自定义类中 class YourTestClass: UIViewController { // 用Set来持有所有Combine订阅,自动管理生命周期 private var cancellables = Set<AnyCancellable>() override func viewDidLoad() { super.viewDidLoad() // SOLUTION 1 修正:添加store(in:)持有订阅 NotificationCenter.default .publisher(for: .Test) .sink(receiveCompletion: { _ in print("SOLUTION 1: COMPLETION") }, receiveValue: { _ in print("SOLUTION 1: VALUE") }) .store(in: &cancellables) // SOLUTION 2 修正:同样添加store(in:) NotificationCenter.Publisher(center: .default, name: .Test) .sink(receiveCompletion: { _ in print("SOLUTION 2: COMPLETION") }, receiveValue: { _ in print("SOLUTION 2: VALUE") }) .store(in: &cancellables) // SOLUTION 3 保持不变 NotificationCenter.default.addObserver(self, selector: #selector(doSomething), name: .Test, object: nil) // 发送通知测试 NotificationCenter.default.post(name: .Test, object: nil) NotificationCenter.default.post(name: .Test, object: nil) } @objc func doSomething() { print("SOLUTION 3: VALUE") } } extension Notification.Name { static let Test = Notification.Name(rawValue: "Test") }
额外小提示
如果只需要管理单个订阅,也可以用单独的AnyCancellable?属性存储:
private var testNotificationCancellable: AnyCancellable? // 赋值方式 testNotificationCancellable = NotificationCenter.default .publisher(for: .Test) .sink(...)
用Set的优势是可以统一管理多个订阅,后续不需要的订阅也可以通过cancel()方法从Set中移除,非常方便。
内容的提问来源于stack exchange,提问作者Luigi Trevisi
相关产品推荐
相关产品推荐

