Home > Software design >  Swift Combine collect values while a condition is true but also one more time after it's true
Swift Combine collect values while a condition is true but also one more time after it's true

Time:10-19

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
*/


CodePudding user response:

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)")
  }
  • Related