Skip to content

Instantly share code, notes, and snippets.

@shaps80
Last active June 18, 2019 18:08
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shaps80/eaa12e5fcddab90a4c6b2fbf321c96e6 to your computer and use it in GitHub Desktop.
Save shaps80/eaa12e5fcddab90a4c6b2fbf321c96e6 to your computer and use it in GitHub Desktop.
A generic cell provider implementation in Swift
//
// ReusableView.swift
// Pods
//
// Created by Shahpour Benkau on 27/02/2017.
//
//
import UIKit
/**
* Represents a general 'cell' type to provide conformance for UITableViewCell and UICollectionViewCell
*/
public protocol ReusableCell: class {
static var reuseIdentifier: String { get }
}
extension ReusableCell {
public static var reuseIdentifier: String {
return String(describing: self)
}
}
extension UITableViewCell: ReusableCell { }
extension UICollectionViewCell: ReusableCell { }
/**
* Represents a general 'view' type to provide conformance for UITableView and UICollectionView. Includes register and dequeue calls so that we can handle both types, or even your own DataView types
*/
public protocol ReusableCellHosting {
func register<C: ReusableCell>(cellClass: C.Type)
func dequeueReusableCell<C: ReusableCell>(ofType cellClass: C.Type, for indexPath: IndexPath) -> C
func dequeueReusableCell<C: ReusableCell>(with identifier: String, for indexPath: IndexPath) -> C
}
extension UITableView: ReusableCellHosting {
public func register<C: ReusableCell>(cellClass: C.Type) {
register(cellClass, forCellReuseIdentifier: cellClass.reuseIdentifier)
}
public func dequeueReusableCell<C: ReusableCell>(ofType cellClass: C.Type, for indexPath: IndexPath) -> C {
return dequeueReusableCell(withIdentifier: cellClass.reuseIdentifier, for: indexPath) as! C
}
public func dequeueReusableCell<C : ReusableCell>(with identifier: String, for indexPath: IndexPath) -> C {
return dequeueReusableCell(withIdentifier: identifier, for: indexPath) as! C
}
}
extension UICollectionView {
public func register<C: ReusableCell>(cellClass: C.Type) {
self.register(cellClass, forCellWithReuseIdentifier: cellClass.reuseIdentifier)
}
public func dequeueReusableCell<C: ReusableCell>(ofType cellClass: C.Type, for indexPath: IndexPath) -> C {
return dequeueReusableCell(withReuseIdentifier: cellClass.reuseIdentifier, for: indexPath) as! C
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(cellClass: PersonCell.self)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if person.role == "Engineer" {
let cell = tableView.dequeueReusableCell(ofType: PersonCell.self, for: indexPath)
cell.textLabel?.text = person.name
cell.detailTextLabel?.text = person.role
return cell
} else {
let cell = tableView.dequeueReusableCell(with: "SubtitleCell", for: indexPath) as UITableViewCell
cell.textLabel?.text = person.name
cell.detailTextLabel?.text = person.role
return cell
}
}
@rolandleth
Copy link

Using something really similar, the only difference being that the methods signatures are a bit less wordy and implemented slightly different:

// I find the first two are obvious we're dequeueing a cell by the types' names, usually.
tableView.register(PersonCell.self)
tableView.dequeue(PersonCell.self, for: indexPath)
// Not gaining much here but it sounds better than the original.
tableView.dequeueCell(withIdentifier: "SubtitleCell", for: indexPath)

Really love using it! And the same goes for UICollectionViewCells.

@shaps80
Copy link
Author

shaps80 commented Mar 7, 2017

I'll consider it -- nice suggestions ;)

My implementation also handles UICollectionView and any other Cell-based views you may import via 3rd party frameworks. Which is one of the main differences in approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment