0

I am new to RxSwift and I would like to achieve something like this. Here's the situation

I have 2 different APIs that needs to populate in a UITableView. Therefore I need to combine 2 sets of data

I would like to achieve something like waiting 2 APIs finish returning the data only then I reload the UITableView once.

I've tried Observable.zip and Observable.combineLatest , but I still cannot get what I want.

Any one can help me on this ?

Edited Here's the idea of how I want it to be done

func viewDidLoad() {
    setupObs()
    getBalance()
    getTransaction()
}

func getBalance() {
    //Call get balance
}

func getTransaction() {
    // Call get transaction
}

func setupObs() {
        Observable.zip(
            getBalance(),
            getTransaction()
        )
        .subscribe(onNext: { bal, trx in
            print("Done")
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposeBag)

}

The output "Done" is being printed twice

cMoNz
  • 13
  • 3
  • `Observable.zip` is exactly the operator you are looking for. Can you provide a code sample so we can have a better understanding of what is missing? – Morniak Dec 05 '22 at 09:54
  • @Morniak , I've included the sample code – cMoNz Dec 06 '22 at 06:21
  • Consider to switch to `Swift Concurrency (async/await)`. It's able to handle those cases much smoother. And what is the benefit of RxSwift over built-in Combine? – vadian Dec 06 '22 at 08:19
  • Why do you call `getBalance` and `getTransaction` in the `viewDidLoad` if you also call them in the `setupObs`? This code cannot compile, the get methods should return an `Observable`. Done could be printed twice if both `getBalance` & `getTransaction` emit two .onNext each. – Morniak Dec 06 '22 at 09:23
  • @Morniak , thanks for the point out , now I am able to achieve what I need , didn't know the `setupObs` is doing the job. Thanks for that , appreciate that – cMoNz Dec 06 '22 at 14:36

1 Answers1

0

The Observable.zip operator is exactly the right one to use. Likely though you are doing something else wrong. Your code should look like this:

Observable.zip(firstAPI(), secondAPI()) { firstResult, secondResult in
    combineData(first: firstResult, second: secondResult) // this must return an array!
}
.bind(to: tableView.rx.items) { tableView, row, item in
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: IndexPath(row: row, section: 0))
    // configure cell with item
    return cell
}
.disposed(by: disposeBag)

Likely, your mistake is that you aren't returning an array from the operator and so the rx.items binder is complaining.

Daniel T.
  • 32,821
  • 6
  • 50
  • 72