Skip to content

Instantly share code, notes, and snippets.

@AlexanderZ-aFrogleap
Created October 15, 2016 20:12
Show Gist options
  • Save AlexanderZ-aFrogleap/e77bc15148e182a1ffde5fb6b1dc8992 to your computer and use it in GitHub Desktop.
Save AlexanderZ-aFrogleap/e77bc15148e182a1ffde5fb6b1dc8992 to your computer and use it in GitHub Desktop.
Generic UITableView adapter with sections
//: Playground - noun: a place where people can play
import UIKit
protocol SectionModel {
var count: Int { get }
func cell(at: Int) -> UITableViewCell
func selected(at: Int)
}
class Adapter: NSObject {
let sections: [SectionModel]
init(sections: [SectionModel]) {
self.sections = sections
}
}
extension Adapter: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section = sections[indexPath.section]
return section.cell(at: indexPath.row)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let section = sections[indexPath.section]
section.selected(at: indexPath.row)
}
}
protocol Adaptable {
associatedtype Model
func adapt(model: Model)
}
class GenericSectionModel<Model, Cell>: SectionModel where Cell: UITableViewCell, Cell: Adaptable, Cell.Model == Model {
typealias ModelCellClosure = (Model, Cell) -> ()
private let items: [Model]
private lazy var cells: [Cell] = self.createCells()
var onSelected: ModelCellClosure? = nil
var count: Int {
return items.count
}
init(items: [Model]) {
self.items = items
}
func cell(at: Int) -> UITableViewCell {
return cells[at]
}
func createCells() -> [Cell] {
return items.map { m in
let c = Cell()
c.adapt(model: m)
return c
}
}
func selected(at: Int) {
let m = items[at]
let c = cells[at]
onSelected?(m, c)
}
}
extension UITableView {
func setAdapter(_ adapter: Adapter) {
dataSource = adapter
delegate = adapter
reloadData()
}
}
// Usage
struct User {
let name: String
}
class UserCell: UITableViewCell, Adaptable {
func adapt(model: User) {
textLabel?.text = model.name
}
}
struct Account {
let id: String
}
class AccountCell: UITableViewCell, Adaptable {
func adapt(model: Account) {
textLabel?.text = model.id
textLabel?.textColor = UIColor.red
}
}
let users = [User(name: "Test User 0"),
User(name: "Test User 1"),
User(name: "Test User 2"),
User(name: "Test User 3"),
User(name: "Test User 4"),
User(name: "Test User 5"),
User(name: "Test User 6")]
let accs = [Account(id: "test_acc")]
let usersSection = GenericSectionModel<User, UserCell>(items: users)
usersSection.onSelected = { m, c in
print(m)
print(c)
}
let accountsSection = GenericSectionModel<Account, AccountCell>(items: accs)
let adapter = Adapter(sections: [usersSection, accountsSection])
let table = UITableView(frame: CGRect(x: 0, y: 0, width: 200, height: 400), style: .grouped)
table.setAdapter(adapter)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment