2

I wasn't really able to find this in docs or somewhere, but is there a way to provide custom header and footer loaded from nib, using RxDatasources?

For example, I am dequeuing a cell like this:

let dataSource = RxTableViewSectionedAnimatedDataSource<CommentsSectionModel>(
                configureCell: { dataSource, tableView, indexPath, item in
                    if let cell = tableView.dequeueReusableCell(withIdentifier: 
                       item.cellIdentifier, for: indexPath) as? BaseTableViewCell{
                       cell.setup(data: item.model)               
                       return cell
                    }
                return UITableViewCell()
 })

I don't see that there is something along with configureCell (except titleForHeaderInSection) to let me dequeue/configure reusable header/footer (something what standard viewForHeaderInSection and viewForFooterInSection delegate methods are providing).

Whirlwind
  • 14,286
  • 11
  • 68
  • 157
  • https://github.com/RxSwiftCommunity/RxDataSources/issues/226#issuecomment-397337413 similar ?? – RTXGamer Dec 28 '21 at 06:50
  • Ok thanks, I guess I could try some of that. I was like, is there any like `configureCell`, like `configureHeaderFooterView`, `configureSupplementaryView` and such... @RTXGamer – Whirlwind Dec 28 '21 at 11:52

2 Answers2

3

A custom Header/Footer is not part of the UITableViewDataSource interface so it's not something that an RxDataSource can provide.

If you want, you can follow my article on how to Convert a Swift Delegate to RxSwift Observables and make a table view delegate for this... It's not part of the library because table view delegates don't conform to a push interface.

extension Reactive where Base: UITableView {
    var delegate: UITableViewDelegateProxy {
        return UITableViewDelegateProxy.proxy(for: base)
    }

    var viewForHeaderInSection: Binder<[Int: UIView]> {
        Binder(delegate) { del, value in
            del.viewForHeaderInSection.accept(value)
        }
    }

    var viewForFooterInSection: Binder<[Int: UIView]> {
        Binder(delegate) { del, value in
            del.viewForFooterInSection.accept(value)
        }
    }
}

final class UITableViewDelegateProxy
: DelegateProxy<UITableView, UITableViewDelegate>
, DelegateProxyType
, UITableViewDelegate {

    public static func registerKnownImplementations() {
        self.register { UITableViewDelegateProxy(parentObject: $0) }
    }

    static func currentDelegate(for object: UITableView) -> UITableViewDelegate? {
        object.delegate
    }

    static func setCurrentDelegate(_ delegate: UITableViewDelegate?, to object: UITableView) {
        object.delegate = delegate
    }

    init(parentObject: UITableView) {
        super.init(
            parentObject: parentObject,
            delegateProxy: UITableViewDelegateProxy.self
        )
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        viewForHeaderInSection.value[section]
    }

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        viewForFooterInSection.value[section]
    }

    fileprivate let viewForHeaderInSection = BehaviorRelay<[Int: UIView]>(value: [:])
    fileprivate let viewForFooterInSection = BehaviorRelay<[Int: UIView]>(value: [:])
}
Daniel T.
  • 32,821
  • 6
  • 50
  • 72
0

@DanielT answer above work for my case, but it only show 1 section header/footer only. I updated it like this and it's fixed:

var viewForHeaderInSection: Binder<[Int: UIView]> {
        Binder(delegate) { del, value in
            let newValue = del.viewForHeaderInSection.value.merging(value, uniquingKeysWith: {(_,new) in new})
            del.viewForHeaderInSection.accept(newValue)
        }
    }

    var viewForFooterInSection: Binder<[Int: UIView]> {
        Binder(delegate) { del, value in
            let newValue = del.viewForFooterInSection.value.merging(value, uniquingKeysWith: {(_,new) in new})
            del.viewForFooterInSection.accept(newValue)
        }
    }
   
code4food
  • 113
  • 1
  • 5