Reputation: 327
I am trying to use Swift combine to run many tasks with the same result. at the moment each task is a publisher that will emit a result. now I am facing a problem that I have to wait for all publishers to emit the element then moving on. kind of like dispatch group. I found zip(with:::_) operator which takes 4 publishers.
https://developer.apple.com/documentation/combine/passthroughsubject/3333571-zip
but what if you have an array of publishers (in case that they emit the same kind of element) ? is there any way to do that?
Upvotes: 19
Views: 14983
Reputation: 197
Well you can use CombineLatest. You can input upto 3 publisher properties and have a single downstream which will be executed once all publishers are received.
As per the example given in WWDC you can use it as follows.
class ViewController: UIViewController {
@IBOutlet private var termsSwitch: UISwitch!
@IBOutlet private var privacySwitch: UISwitch!
@IBOutlet private var nameField: UITextField!
@IBOutlet private var submitButton: UIButton!
@Published private var acceptedTerms: Bool = false
@Published private var acceptedPrivacy: Bool = false
@Published private var name: String = ""
// Keep a reference to the subscription so it's
// only cancelled when we are deallocated.
private var termsStream: AnyCancellable?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
termsStream = validToSubmit
.receive(on: RunLoop.main)
.assign(to: \.isEnabled, on: submitButton)
}
@IBAction private func acceptTerms(_ sender: UISwitch) {
acceptedTerms = sender.isOn
}
@IBAction private func acceptPrivacy(_ sender: UISwitch) {
acceptedPrivacy = sender.isOn
}
@IBAction private func nameChanged(_ sender: UITextField) {
name = sender.text ?? ""
}
private var validToSubmit: AnyPublisher<Bool, Never> {
return Publishers.CombineLatest3($acceptedTerms, $acceptedPrivacy, $name)
.map { terms, pricacy, name in
terms && pricacy && !name.isEmpty
}.eraseToAnyPublisher()
}
Upvotes: 1
Reputation: 54716
You can use MergeMany
to create a single downstream receiving all emitted values from several upstreams and then call collect()
on the merged publisher to emit all values at once.
let pubs = [Just(1),Just(2),Just(3)]
let downstream = Publishers.MergeMany(pubs).collect()
Upvotes: 32