Swift中使用Combine筛选收集两个数组差异元素的问题排查
问题分析与修正方案
你的代码存在几个关键问题,导致无法输出预期结果,以下是具体问题和修正后的实现:
核心问题点
- 订阅时机错误:你先给
subject1和subject2发送了元素,之后才创建订阅。PassthroughSubject是热信号,无订阅者时发送的元素会直接丢失,必须先完成订阅逻辑再发送元素。 - 序列处理逻辑错误:
zip(array1, array2)返回的是Zip2Sequence对象,直接用map返回该序列的话,下游拿到的是整个序列而非逐个发射的元素,无法实现单元素筛选。 - 类型不匹配:
filteredSubject定义为接收[Int]类型,但下游sink里发送的是单个Int元素,类型不兼容。 - 缺少订阅容器:未定义
Set<AnyCancellable>保存订阅对象,订阅会被立即释放,无法接收信号。
修正后的代码(逐个发射差异元素)
import Combine // 定义订阅容器,保存所有订阅对象 var subscriptions = Set<AnyCancellable>() let subject1 = PassthroughSubject<[Int], Never>() let subject2 = PassthroughSubject<[Int], Never>() // 调整为接收单个Int元素 let filteredSubject = PassthroughSubject<Int, Never>() // 先完成所有订阅逻辑 Publishers.CombineLatest(subject1, subject2) .flatMap { array1, array2 in // 将Zip2Sequence转换为Combine流,逐个发射元素对 Publishers.Sequence(sequence: zip(array1, array2)) } .filter { element1, element2 in element1 != element2 } .map { $0.0 } // 取出差异的第一个数组元素 .sink(receiveValue: { filteredElement in filteredSubject.send(filteredElement) }) .store(in: &subscriptions) filteredSubject .sink(receiveValue: { filteredElement in print("Filtered Element:", filteredElement) }) .store(in: &subscriptions) // 最后发送元素与完成信号 subject1.send([4, 5, 6, 8]) subject2.send([4, 5, 7, 9]) subject1.send(completion: .finished) subject2.send(completion: .finished)
另一种实现(直接发送差异元素数组)
如果需要将所有差异元素收集成数组后一次性发送,可简化逻辑:
import Combine var subscriptions = Set<AnyCancellable>() let subject1 = PassthroughSubject<[Int], Never>() let subject2 = PassthroughSubject<[Int], Never>() let filteredSubject = PassthroughSubject<[Int], Never>() Publishers.CombineLatest(subject1, subject2) .map { array1, array2 in // 直接计算对应位置的差异元素数组 zip(array1, array2) .filter { $0 != $1 } .map { $0.0 } } .sink(receiveValue: { filteredArray in filteredSubject.send(filteredArray) }) .store(in: &subscriptions) filteredSubject .sink(receiveValue: { filteredElements in print("Filtered Elements:", filteredElements) }) .store(in: &subscriptions) subject1.send([4, 5, 6, 8]) subject2.send([4, 5, 7, 9]) subject1.send(completion: .finished) subject2.send(completion: .finished)
内容的提问来源于stack exchange,提问作者Jael Ruvalcaba
相关产品推荐
相关产品推荐

