Search code examples
iosrx-swiftrx-cocoa

RxCocoa-observable is emitting new data from API but tableview.rx.items doesn't show new data


I am new to both RxSwift and RxCocoa.

I have a working REST service on local which returns a Movie object for given "id".

On my storyboard there is a tableView (UITableView) which has custom cells (MovieCell). Each movie cell has a UILabel named "nameTextLabel". I also have a textField to get requested movie.id from user.

I am trying to show movie.title on each row of my tableView.

import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {

@IBOutlet var textField: UITextField!
@IBOutlet var tableView: UITableView!
let bag = DisposeBag()

override func viewDidLoad() {
    super.viewDidLoad()
    configureReactiveBinding()
}
private func configureReactiveBinding() {
    textField.rx.text.asObservable()
        .map { ($0 == "" ? "15" : $0!).lowercased() }
        .map { GetMovieByIdRequest(id: $0) }
        .flatMap { request -> Observable<Movie> in
            return ServiceManager.instance.send(apiRequest: request)
        }
    .debug("movie")
// output:
//2018-10-17 16:13:49.320: movie -> subscribed
//2018-10-17 16:13:49.401: movie -> Event next(MovieAdvisor.Movie)
//2018-10-17 16:13:52.021: movie -> Event next(MovieAdvisor.Movie)
    .toArray()
    .debug("tableView")
// output:
//2018-10-17 16:13:49.318: tableView -> subscribed

        .bind(to: tableView.rx.items(cellIdentifier: "movie_cell", cellType:MovieCell.self)) { index, model, cell in
            cell.nameTextLabel.text = model.title
        }
        .disposed(by: bag)
}

}

Each time textLabel is changed the new movie.id is printed, but tableView doesn't show any data-not even with initial value (when textField is "").

Any idea how can i fix this?

After adding debug() lines, i figured that tableView is subscribed just once and no next events triggered tableView. What should i do? Code is uploaded on GitHub github


Solution

  • Try replacing

    `a.subscribe(onNext: {movie in
        print(movie.title)
    })
    .disposed(by: bag)
    

    with .observeOn(MainScheduler.instance) and see whether it does the trick.

    Perhaps move .toArray() to directly after ServiceManager.instance.send(apiRequest: request).

    Also you can add *.debug("my custom message")* after every RxSwift operator to see whether it is getting executed.

    BTW I would recommend using RxDataSources framework for this, not bare RxCocoa.