RxDataSources icon indicating copy to clipboard operation
RxDataSources copied to clipboard

More simple RxTableViewSectionedAnimatedDataSource API for single section.

Open hikaruna opened this issue 7 years ago • 6 comments

enhancement

Please forgive my poor English.

expected

struct CustomData {
    let id = UUID()
    var anInt: Int
    var aString: String
    var aCGPoint: CGPoint
}

extension CustomData: IdentifiableType, Hashable {
    typealias Identity = Int

    static func == (lhs: CustomData, rhs: CustomData) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
    
    var hashValue: Int {
        return id.hashValue
    }

    var identity: Int {
        return hashValue
    }
}

// I want to eliminate the need to define
//- struct SectionOfCustomData {
//-  var header: String    
//-   var items: [Item]
//- }
//- extension SectionOfCustomData: SectionModelType {
//-   typealias Item = CustomData
//- 
//-    init(original: SectionOfCustomData, items: [Item]) {
//-     self = original
//-     self.items = items
//-   }
//- }


let dataSource = RxTableView/*-Sectioned-*/ReloadDataSource<CustomData>(
  configureCell: { dataSource, tableView, indexPath, item in
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)"
    return cell
})

let items = [
    CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero),
    CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1))
]

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

  • RxTableViewAnimatedDataSource for single section RxTableViewSectionedAnimatedDataSource( I want)
  • RxTableViewReloadDataSource for single section RxTableViewSectionedReloadDataSource

Thanks.

hikaruna avatar Sep 30 '18 15:09 hikaruna

You can directly use SectionModel<String, CustomData> :)

You still need to adhere to the Equatable protocol though.

sauravexodus avatar Sep 30 '18 18:09 sauravexodus

I think, If it is single section table, Developers do not need to manage sections. I want to manage only itemsArray.

hikaruna avatar Oct 01 '18 15:10 hikaruna

My idea. https://gist.github.com/lm2343635/79419495dd691b9253bb326671019c55


import RxDataSources

// SectionedReloadDataSource
struct SingleSectionModel<T>: SectionModelType {
    
    typealias Item = T
    
    var items: [T]
    
    init(items: [T]) {
        self.items = items
    }
    
    init(original: SingleSectionModel<T>, items: [T]) {
        self = original
    }
    
    static func create(_ items: [T]) -> SingleSection<T> {
        return [SingleSectionModel(items: items)]
    }
    
}

typealias SingleSection<T> = [SingleSectionModel<T>]

extension SingleSection where Element: SectionModelType {
    static func create(_ items: [Element.Item]) -> SingleSection<Element.Item> {
        return [SingleSectionModel(items: items)]
    }
}

typealias TableViewSingleSectionDataSource<T> = RxTableViewSectionedReloadDataSource<SingleSectionModel<T>>
typealias CollectionViewSingleSectionDataSource<T> = RxCollectionViewSectionedReloadDataSource<SingleSectionModel<T>>

// AnimatableSectionedReloadDataSource
protocol AnimatableModel: IdentifiableType, Equatable {}

struct AnimatableSingleSectionModel<T: AnimatableModel>: AnimatableSectionModelType {
    
    typealias Item = T
    typealias Identity = String
    
    var items: [T]
    var identity: String
    
    init(items: [T]) {
        self.items = items
        self.identity = ""
    }
    
    init(original: AnimatableSingleSectionModel<T>, items: [T]) {
        self = original
        self.items = items
    }
    
    static func create(_ items: [T]) -> AnimatableSingleSection<T> {
        return [AnimatableSingleSectionModel(items: items)]
    }
    
}

typealias AnimatableSingleSection<T: AnimatableModel> = [AnimatableSingleSectionModel<T>]

extension AnimatableSingleSection where Element: AnimatableSectionModelType, Element.Item: AnimatableModel {
    static func create(_ items: [Element.Item]) -> AnimatableSingleSection<Element.Item> {
        return [AnimatableSingleSectionModel(items: items)]
    }
}

typealias TableViewAnimatedSingleSectionDataSource<T: AnimatableModel> = RxTableViewSectionedAnimatedDataSource<AnimatableSingleSectionModel<T>>
typealias CollectionViewAnimatedSingleSectionDataSource<T: AnimatableModel> = RxCollectionViewSectionedAnimatedDataSource<AnimatableSingleSectionModel<T>>

lm2343635 avatar Oct 05 '18 08:10 lm2343635

Thank you. I learned a lot.

I was able to combine the information of the two people.

class TableViewController: UITableViewController {
    var items: Variable<[CustomData]> = Variable([])

    override func viewDidLoad() {
        super.viewDidLoad()

        let dataSource = RxTableViewAnimatedDataSource<CustomData>(configureCell: { (_, tableView, indexPath, item) in
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
            cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)"
            return cell
        })

        items.asObservable()
            .map({ AnimatableRowsModel.create(items: $0) })
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: bag)
    }
}

hikaruna avatar Oct 06 '18 20:10 hikaruna

Thank you.

By referring to your comment, I simply applied it like this.

typealias RxTableViewAnimatedDataSource<ItemType: IdentifiableType & Equatable> = RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, ItemType>>

typealias AnimatableRowsModel<T: IdentifiableType & Equatable> = [AnimatableSectionModel<Int, T>]
extension AnimatableRowsModel where Element: AnimatableSectionModelType {
    static func create(items: [Element.Item]) -> AnimatableRowsModel<Element.Item> {
        return [AnimatableSectionModel(model: 0, items: items)]
    }
}
class TableViewController: UITableViewController {

    var items: Variable<[CustomData]> = Variable([])

    override func viewDidLoad() {
        super.viewDidLoad()

        let dataSource = RxTableViewAnimatedDataSource<CustomData>(configureCell: { (_, tableView, indexPath, item) in
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
            cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)"
            return cell
        })

        items.asObservable()
            .map({ AnimatableRowsModel.create(items: $0) })
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: bag)
    }
}

But, Such programming is slightly more difficult. The reason I used RxTableViewDataSources was I just wanted to animate the following samples.

searchResults
  .bind(to: tableView.rx.items(cellIdentifier: "Cell")) { (index, repository: Repository, cell) in         
    cell.textLabel?.text = repository.name
    cell.detailTextLabel?.text = repository.url
  }
  .disposed(by: disposeBag)

I hope that a simple API will be officially implemented.

hikaruna avatar Oct 06 '18 20:10 hikaruna

Agreed @hikaruna. Sometimes its lot of unwrapping code if you want to manipulate a single section table data source array.

sauravexodus avatar Oct 07 '18 19:10 sauravexodus