Skip to content

Instantly share code, notes, and snippets.

@lamprosg
Last active October 11, 2018 13:19
Show Gist options
  • Select an option

  • Save lamprosg/644fb794c7cf7ac5456028e26e661ca6 to your computer and use it in GitHub Desktop.

Select an option

Save lamprosg/644fb794c7cf7ac5456028e26e661ca6 to your computer and use it in GitHub Desktop.
(iOS) Generic tableview datasource
//Variation of this feature: https://www.swiftbysundell.com/posts/reusable-data-sources-in-swift
import UIKit
/// Keep a strong reference to this, since UITableView only uses a weak reference for it. Used only for simple table views fast rendering.
class TableViewCommonCellDataSource<Model>: NSObject, UITableViewDataSource {
/// Cell configuration
typealias CellConfigurator = (Model, UITableViewCell) -> Void
var models: [Model]
private let reuseIdentifier: String
private let cellConfigurator: CellConfigurator
init(models: [Model], reuseIdentifier: String, cellConfigurator: @escaping CellConfigurator) {
self.models = models
self.reuseIdentifier = reuseIdentifier
self.cellConfigurator = cellConfigurator
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return models.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = models[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)
//Run cell setup here, taken by the closure in the initializer.
cellConfigurator(model, cell)
return cell
}
}
func messagesDidLoad(_ messages: [Message]) {
let dataSource = TableViewDataSource(
models: messages,
reuseIdentifier: "message"
) { message, cell in
cell.textLabel?.text = message.title
cell.detailTextLabel?.text = message.preview
}
// We also need to keep a strong reference to the data source,
// since UITableView only uses a weak reference for it.
self.dataSource = dataSource
tableView.dataSource = dataSource
}
extension TableViewDataSource where Model == Message {
static func make(for messages: [Message],
reuseIdentifier: String = "message") -> TableViewDataSource {
return TableViewDataSource(
models: messages,
reuseIdentifier: reuseIdentifier
) { (message, cell) in
cell.textLabel?.text = message.title
cell.detailTextLabel?.text = message.preview
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment