So I want to collect values until I see the last page, but if the last page never comes I want to send what we have, given a time limit.
I have a way of doing this but it seems rather wasteful. I'm going to be using this to make collections that may have hundreds of thousands of values, so a more space-efficient method would be preferred.
You can copy and paste the following into a playground
import UIKit
import Foundation
import Combine
var subj = PassthroughSubject<String, Never>()
let queue = DispatchQueue(label: "Test")
let collectForTime = subj
.collect(.byTime(queue, .seconds(10)))
let collectUntilLast = subj
.scan([String]()) { $0 + [$1] }
.first { $0.last == "LastPage" }
// whichever happens first
let cancel = collectForTime.merge(with: collectUntilLast)
.first()
.sink {
print("complete1: \($0)")
} receiveValue: {
print("received1: \($0)")
}
print("start")
let strings = [
"!@#$",
"ZXCV",
"LastPage", // comment this line to test to see what happens if no last page is sent
"ASDF",
"JKL:"
]
// if the last page is present then the items 0..<3 will be sent
// if there's no last page then send what we have
// the main thing is that the system is not just sitting there waiting for a last page that never comes.
for i in (0..<strings.count) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(i)) {
let s = strings[i]
print("sending \(s)")
subj.send(s)
}
}