Skip to content

Instantly share code, notes, and snippets.

@janodev
Created February 17, 2020 00:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janodev/7541cb4ac5f9878f30c3902ed51d523c to your computer and use it in GitHub Desktop.
Save janodev/7541cb4ac5f9878f30c3902ed51d523c to your computer and use it in GitHub Desktop.
Generic collection
import UIKit
class Cell<C: UIView & CellViewType>: UICollectionViewCell
{
private let cellView: C
override init(frame: CGRect){
cellView = C()
super.init(frame: frame)
contentView.addSubview(cellView)
cellView.frame = bounds
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension Cell: CellType
{
typealias T = C.T
func configure(object: T) {
cellView.configure(object: object)
}
static func identifier()->String {
return String(describing: type(of: self))
}
}
protocol CellType
{
associatedtype T
static func identifier()->String
func configure(object: T)
}
protocol CellViewType
{
associatedtype T
func configure(object: T)
}
import UIKit
class CollectionDataSource<C: CellType>: NSObject, UICollectionViewDataSource
{
var data = [C.T]()
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: C.identifier(), for: indexPath)
if let cell = cell as? C {
cell.configure(object: data[indexPath.row])
}
return cell
}
}
struct Task {
let title: String
}
class TaskCell: Cell<TaskCellView> {}
import UIKit
final class TaskCellView: UIView
{
private let label = UILabel()
init() {
super.init(frame: CGRect.zero)
initialize()
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("unavailable")
}
private func initialize()
{
backgroundColor = UIColor.white
addSubview(label)
let views: [String: UIView] = ["label" : label]
views.values.forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
for constraint in [
"H:|[label]|",
"V:|[label]|"
] {
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: [], metrics: nil, views: views))
}
}
}
extension TaskCellView: CellViewType
{
typealias T = Task
func configure(object: T) {
label.text = "\(object)"
}
}
import UIKit
class ViewController: UIViewController
{
private lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: CollectionViewLayout(display: .list))
collectionView.register(TaskCell.self, forCellWithReuseIdentifier: TaskCell.identifier())
collectionView.dataSource = datasource
return collectionView
}()
private let datasource = CollectionDataSource<TaskCell>()
override func loadView() {
view = collectionView
}
override func viewDidLoad() {
super.viewDidLoad()
datasource.data = createData(closedRange: 0...10)
}
private func createData(closedRange: ClosedRange<Int>) -> [Task] {
let nf = NumberFormatter()
nf.numberStyle = .spellOut
return closedRange.compactMap {
nf.string(from: NSNumber(integerLiteral: $0))
.flatMap { Task.init(title: $0.description) }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment