Anjaneyulu Battula
Anjaneyulu Battula

Reputation: 1960

Swft3 (RxSwift, RxCocoa) - TableView Expand and collapse concept using reactive programming

Recently started writing code in Swift using reactive programming. Reactive programming is little confusing concept, anyway i want to implement tableview with expand and collapse concept using reactive programming. I tried in my own way, i am able to write code for implementing normal, section tableview and here they provided examples also, but for expand and collapse tableview i did not find any example. Can any one please provide the solution for this.

Upvotes: 0

Views: 1737

Answers (1)

farzadshbfn
farzadshbfn

Reputation: 2748

I Assume you're familiar with "combineLatest". This answer is not really "clean" but will somehow give the idea of how to implement it:

first define an array:

var expansions = [Variable<Bool>].init(repeating: Variable<Bool>(true), count: 2)

I only had 2 sections in my case, If you have unknown number of sections you have to use [Int: Variable<Bool>] to map each section into this dictionary.

now define a method for getting the expansion:

func expansion(for section: Int) -> Variable<Bool> {
    /* if using [Int: Variable<Bool>]
    if expansions[section] == nil {
        expansions[section = Variable<Bool>(false)
    }*/
    return expansions[section]
}

now filter your items using Observable.combineLatest and expansion(for: _)

And in tableView delegate:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    // next line just dequeues a UITableViewHeaderFooterView subclass.
    let view = tableView.dequeueReusableHeaderFooter(forSection: section) as ExpandableHeader
    view.titleLabel.text = dataSource[section].model.title
    view.isExpanded = expansions[section].value // just a variable to update header's UI
    view.expandButton.rx.controlEvent(.touchUpInside)
        .bind { [weak self, weak view = view] in
            guard let strongSelf = self else { return }
            strongSelf.expansions[section].value = !strongSelf.expansions[section].value
            view?.isExpanded = strongSelf.expansions[section].value // because dataSource will not reload this view itself unless it gets dequeued.
    }
    .disposed(by: view.disposeBag)
    return view
}

Notice

I'm disposing this subscription with view.disposeBag not the one i'm using in this viewController. because view.disposeBag will get renewed in prepareForReuse() every-time, and will remove all previous subscribers. (not using such method, will not cause memory-leak, but it will cause ViewController to consume lots of resources and of-course unwanted behavior)

Upvotes: 0

Related Questions