如何擦除NotificationCenter.Notifications类型?解决Sendable兼容报错
解决Notification异步序列merge时的Sendable合规问题
问题根源在于:尽管你通过map将Notification转换为Void,但NotificationCenter.Notifications这个底层异步序列本身并未遵循Sendable协议,而merge()要求输入的异步序列必须满足Sendable约束,因此报错依然存在。
以下是两种可行的解决方法:
方法一:使用AsyncChannel中转(推荐)
通过AsyncChannel将非Sendable的通知序列转换为Sendable的事件流,完全符合Swift并发安全规范:
import AsyncAlgorithms import Foundation extension Notification.Name { static let noteOne = Notification.Name("noteOne") static let noteTwo = Notification.Name("noteTwo") } // 创建用于中转事件的异步通道 let channel1 = AsyncChannel<Void>() let channel2 = AsyncChannel<Void>() // 启动任务监听通知,收到时向通道发送空值 Task { for await _ in NotificationCenter.default.notifications(named: .noteOne) { await channel1.send() } } Task { for await _ in NotificationCenter.default.notifications(named: .noteTwo) { await channel2.send() } } // 合并两个通道的事件流 let merged = merge(channel1, channel2) // 监听合并后的事件 Task { for await _ in merged { print("触发目标事件") } }
方法二:显式标记序列为@unchecked Sendable
若你仅关心通知触发、不处理任何Notification内容,可安全地将转换后的序列标记为@unchecked Sendable,快速满足merge()的约束:
import AsyncAlgorithms import Foundation extension Notification.Name { static let noteOne = Notification.Name("noteOne") static let noteTwo = Notification.Name("noteTwo") } // 转换序列并标记为@unchecked Sendable let note1 = NotificationCenter.default.notifications(named: .noteOne) .map { _ in () } .eraseToAnyAsyncSequence() as any AsyncSequence & @unchecked Sendable let note2 = NotificationCenter.default.notifications(named: .noteTwo) .map { _ in () } .eraseToAnyAsyncSequence() as any AsyncSequence & @unchecked Sendable // 合并序列 let merged = merge(note1, note2) // 监听事件 Task { for await _ in merged { print("触发目标事件") } }
注意:使用
@unchecked Sendable时,需确保你确实没有保留或传递任何非Sendable的Notification相关数据,避免并发安全隐患。
内容的提问来源于stack exchange,提问作者Rudedog
相关产品推荐
相关产品推荐

