0

Sorry for the awkward phrasing. Seeing the example below will probably answer all your questions.

So the scenario is that I want to observe a stream of values and collect all the values up until I witness a value. But I also want that value I've witnessed to be added to the colleciton.

So in the example, I'm showing I missing the value 'lastPage'

I made this in a playground in XCode 13.4.1

import Foundation
import Combine

var subj = PassthroughSubject<String, Never>()

let cancel = subj.prefix{
    $0 != "LastPage"
}
.collect(.byTime(DispatchQueue(label: "Test"), .seconds(3)))
.sink {
    print("complete: \($0)")
} receiveValue: {
    print("received: \($0)")
}

print("start")

let strings = [
    "!@#$",
    "ZXCV",
    "LastPage",
    "ASDF",
    "JKL:"
]

for i in (0..<strings.count) {
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(i)) {
        let s = strings[i]
        print("sending \(s)")
        subj.send(s)
    }
}

/* this prints the following
start
sending !@#$
sending ZXCV
sending LastPage
received: ["!@#$", "ZXCV"] <<<< I want this array to include 'LastPage'
complete: finished
sending ASDF
*/


Yogurt
  • 2,913
  • 2
  • 32
  • 63
  • I found a way with using `prefix(untilOutputFrom:)` and using a publisher that finds the page and then sends true with a delay to trigger prefix to close. I don't really like it since it leaves the door open for values to sneak in. I suppose I'll take it if nobody else can think of a better way. – Yogurt Oct 18 '22 at 01:03

1 Answers1

0

You can use scan and first(where:):

let cancel = subj
  .scan([String]()) { $0 + [$1] }
  .first { $0.last == "LastPage" }
  .sink {
    print("complete: \($0)")
  } receiveValue: {
    print("received: \($0)")
  }
Fabio Felici
  • 2,841
  • 15
  • 21
  • I have a follow up question over here https://stackoverflow.com/questions/74115465/swift-combine-collect-values-until-last-page-is-found-or-until-time-expires – Yogurt Oct 18 '22 at 17:59