0

I have a question: how to properly implement such a scenario in Rx-way with RxDataSources:

We have a class with UICollectionView (or UITableView, in my case it's collection view), the results are not immediately present, they come asynchronously after some time.

I have implemented my model with sections according to the tutorial here: https://github.com/RxSwiftCommunity/RxDataSources

But the data is created only once with just there:

let 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)
  .bindTo(collectionView.rx.items(dataSource: dataSource))
  .addDisposableTo(disposeBag)

What to do in case my items are available after some time and I want my collection view to be updated automatically?

Thanks for any help.

jonaszmclaren
  • 2,459
  • 20
  • 30

1 Answers1

6

You can use Variable<[Section]> like this:

enum Api {
    /// Network response
    static func call() -> Observable<[CustomData]> {
        return .just([CustomData(anInt: 0)])
    }
}

struct CustomData {
    let anInt: Int
}

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    typealias Section = SectionModel<String, CustomData>
    private let sections = Variable<[Section]>([])
    private let dataSource = RxTableViewSectionedReloadDataSource<Section>()
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        // change sections by api call
        Api.call()
            .map { (customDatas) -> [Section] in
                [Section(model: "First section", items: customDatas)]
            }.bindTo(sections)
            .addDisposableTo(disposeBag)

        sections.asDriver()
            .drive(tableView.rx.items(dataSource: dataSource))
            .addDisposableTo(disposeBag)

    }

    @IBAction func removeLastTableViewSection() {
        // or you can change the sections manually.
        sections.value.removeLast()
    }
}

The UI will update automatically when you change sections.value.

Hope this may help you.

beeth0ven
  • 1,857
  • 15
  • 18
  • @beeth0ven Can you please help me in similar issue [here](http://stackoverflow.com/questions/42744360/observable-array-to-any-array) I don't know how to convert that Observable to .just as you have mentioned in call function. – Ani Shroff Mar 12 '17 at 08:17
  • Using a `Variable` isn't a particularly reactive way of solving the problem, since now you've created a stateful environment again. Better to listen to a `tap` event and define the `sections` variable accordingly. – RamwiseMatt Jul 11 '17 at 11:46