Last active
March 9, 2021 20:29
-
-
Save Koshimizu-Takehito/717a40a309c635a47fb677c738f8ba4e to your computer and use it in GitHub Desktop.
DataSource, CellProvider をビューコントローラから委譲するサンプルコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
extension UITableView { | |
func register(_ type: UITableViewCell.Type, identifier: String? = nil) { | |
self.register(type, forCellReuseIdentifier: identifier ?? String(describing: type)) | |
} | |
func register(@ArrayBuilder<UITableViewCell.Type> builder: () -> [UITableViewCell.Type]) { | |
builder().forEach { type in | |
register(type) | |
} | |
} | |
func dequeue<Cell: UITableViewCell>(_ type: Cell.Type = Cell.self, identifier: String? = nil, for indexPath: IndexPath) -> Cell { | |
self.dequeueReusableCell(withIdentifier: identifier ?? String(describing: type), for: indexPath) as! Cell | |
} | |
} | |
@_functionBuilder | |
struct ArrayBuilder<T> { | |
static func buildBlock(_ items: T...) -> [T] { | |
items | |
} | |
} | |
class ArrayDataSource<Item>: NSObject, UITableViewDataSource { | |
typealias CellProvider = (UITableView, IndexPath, Item) -> UITableViewCell? | |
private let cellProvider: CellProvider | |
private var items: [[Item]] = [] | |
private unowned let tableView: UITableView | |
init(tableView: UITableView, cellProvider: @escaping CellProvider) { | |
self.cellProvider = cellProvider | |
self.tableView = tableView | |
super.init() | |
tableView.dataSource = self | |
} | |
func apply(multiSectionItems items: [[Item]]) { | |
self.items = items | |
self.tableView.reloadData() | |
} | |
func apply(items: [Item] = []) { | |
self.apply(multiSectionItems: [items]) | |
} | |
func apply(@ArrayBuilder<Item> builder: () -> [Item]) { | |
self.apply(items: builder()) | |
} | |
func numberOfSections(in tableView: UITableView) -> Int { | |
items.count | |
} | |
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
items[section].count | |
} | |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
cellProvider(tableView, indexPath, items[indexPath.section][indexPath.row])! | |
} | |
} | |
enum Item { | |
case foo(FooItem) | |
case bar(BarItem) | |
case baz(BazItem) | |
} | |
struct FooItem { | |
} | |
struct BarItem { | |
} | |
struct BazItem { | |
} | |
class FooTableViewCell: UITableViewCell { | |
class func configure(cell: FooTableViewCell, with item: FooItem) -> FooTableViewCell { | |
return cell | |
} | |
} | |
class BarTableViewCell: UITableViewCell { | |
class func configure(cell: BarTableViewCell, with item: BarItem) -> BarTableViewCell { | |
return cell | |
} | |
} | |
class BazTableViewCell: UITableViewCell { | |
class func configure(cell: BazTableViewCell, with item: BazItem) -> BazTableViewCell { | |
return cell | |
} | |
} | |
class ViewController: UIViewController { | |
@IBOutlet private weak var tableView: UITableView! | |
private lazy var dataSource = ArrayDataSource( | |
tableView: tableView, | |
cellProvider: Provider.provide | |
) | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
tableView.register { | |
FooTableViewCell.self | |
BarTableViewCell.self | |
BazTableViewCell.self | |
} | |
dataSource.apply { | |
Item.foo(FooItem()) | |
Item.foo(FooItem()) | |
Item.bar(BarItem()) | |
Item.bar(BarItem()) | |
Item.bar(BarItem()) | |
Item.baz(BazItem()) | |
Item.baz(BazItem()) | |
Item.baz(BazItem()) | |
Item.baz(BazItem()) | |
} | |
} | |
} | |
private struct Provider { | |
static func provide(tableView: UITableView, indexPath: IndexPath, item: Item) -> UITableViewCell { | |
switch item { | |
case let .foo(item): | |
return FooTableViewCell.configure( | |
cell: tableView.dequeue(for: indexPath), | |
with: item | |
) | |
case let .bar(item): | |
return BarTableViewCell.configure( | |
cell: tableView.dequeue(for: indexPath), | |
with: item | |
) | |
case let .baz(item): | |
return BazTableViewCell.configure( | |
cell: tableView.dequeue(for: indexPath), | |
with: item | |
) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment