Search code examples
rx-swiftrxdatasources

RxSwift, RxDataSources: How to bind dynamic data to UITableView by using RxDataSources?


after binding some data to UITableView by this codes:

struct CustomData {
    var anInt: Int
    var aString: String
    var aCGPoint: CGPoint
}

struct SectionOfCustomData {
    var header: String
    var items: [CustomData]
}
extension SectionOfCustomData: SectionModelType {

    init(original: SectionOfCustomData, items: [CustomData]) {
        self = original
        self.items = items
    }
}


class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    let disposeBag = DisposeBag()
    var data: RxTableViewSectionedReloadDataSource<SectionOfCustomData>?


override func viewDidLoad() {
        super.viewDidLoad()

        let x = status.asObservable()

        tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "Cell")
        tableView.register(UINib(nibName: "TableViewCellTwo", bundle: nil), forCellReuseIdentifier: "Cell2")


data = RxTableViewSectionedReloadDataSource<SectionOfCustomData>(configureCell: { dataSource, tableView, indexPath, item in

            if indexPath.section > 0 {

                let cell = tableView.dequeueReusableCell(withIdentifier: "Cell2", for: indexPath) as! TableViewCellTwo
                cell.age.text = "\(item.anInt)"
                return cell
            }else {

                let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell
                cell.name.text = item.aString
                cell.age.text = "\(item.anInt)"
                return cell
            }
        })

sections = [
            SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
            SectionOfCustomData(header: "Second section", items: [CustomData(anInt: 2, aString: "two", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 3, aString: "three", aCGPoint: CGPoint(x: 3, y: 3)) ])
        ]

Observable.just(sections)
    .bind(to: tableView.rx.items(dataSource: data!))
    .disposed(by: disposeBag)

after pushing button and calling a function, I changing data inside sections var:

@IBAction func change(_ sender: UIButton) {

sections = [
            SectionOfCustomData(header: "third section", items: [CustomData(anInt: 4, aString: "four", aCGPoint: CGPoint.zero), CustomData(anInt: 5, aString: "five", aCGPoint: CGPoint(x: 1, y: 1)) ]),
            SectionOfCustomData(header: "fourth section", items: [CustomData(anInt: 6, aString: "six", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 7, aString: "seven", aCGPoint: CGPoint(x: 3, y: 3)) ])
        ]

but after calling function UITableView data not changing, My question is why after binding section variable to UITableView and changing data inside of that(section), UITableView still showing that last data?


Solution

  • Because the change is not getting into the observable. What you need is following -

    // in class body
    var dataSubject = PublishSubject<[SectionOfCustomData]>()
    
    // in viewDidLoad() method
    dataSubject
      .bind(to: tableView.rx.items(dataSource: data!))
      .disposed(by: disposeBag)
    
    dataSubject.onNext([ /* your initial sections */ ])
    
    // in change() method
    dataSubject.onNext([ /* your new sections */ ])