的水槽.在' publisher '之后没有调用receiveValue '.收到(:backgro



使用下面的代码,在我放入receive(on: backgroundQueue)之后,receiveCompletion将被称为100%,但receiveValue块不是。

xxxxPublisher
.xxxx()
.receive(on: backgroundQueue)
.xxxx()
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
// completion code
}, receiveValue: { value in
// receive value code
}).store(in: &cancellables)

这似乎不是一个好的行为,我们不应该这样使用receive<S>(on scheduler: S, options: S.SchedulerOptions? = nil)吗?我错过什么了吗?

下面是重现这个bug的代码,如果你运行这段代码,你会看到receiveCompletion被调用了正好300次,但是receiveValue被调用的次数少于300次。

import Foundation
import Combine
private var cancellables: Set<AnyCancellable> = []
let backgroundQueue = DispatchQueue.global(qos: .background)
for i in 1...300 {
runPublisher(i)
}
var sinkCompletedIndices = Set<Int>()
var sinkOutputIndices = Set<Int>()
func runPublisher(_ index: Int) {
[1].publisher
.receive(on: backgroundQueue)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
NSLog("sink receiveCompletion")
sinkCompletedIndices.insert(index)
}, receiveValue: { value in
NSLog("sink receiveValue")
sinkOutputIndices.insert(index)
}).store(in: &cancellables)
}
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
let diff = sinkCompletedIndices.filter { !sinkOutputIndices.contains($0) }
NSLog("Difference between completions and outputs (diff)")
}
RunLoop.main.run()

问题是Combine期望调度器作为串行队列操作,但是DispatchQueue。全局是并发的

如果你这样声明后台队列:

let backgroundQueue = DispatchQueue(label: "any name will do", qos: .background)

一切都会如你所愿。

在Swift论坛上有一个有趣的讨论:

https://forums.swift.org/t/runloop-main-or-dispatchqueue-main-when-using-combine-scheduler/26635

相关内容

  • 没有找到相关文章

最新更新