-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathAnyListItem.swift
105 lines (88 loc) · 3.44 KB
/
AnyListItem.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import Foundation
public protocol ListContainerView: class {}
public protocol ListViewCell: class {}
#if os(iOS)
import UIKit
extension UITableView: ListContainerView {}
extension UICollectionView: ListContainerView {}
extension UITableViewCell: ListViewCell {}
extension UICollectionViewCell: ListViewCell {}
#endif
public protocol ListItemType: Diffable {
/// The reuse identifier for the cell passed as argument.
var reuseIdentifier: String { get set }
/// The TableView, or the CollectionView that will own this element.
var referenceView: ListContainerView? { get }
/// A opaque pointer to the model associated to this row.
var modelRef: Any? { get }
/// Configure the cell with the current item.
func configure(cell: ListViewCell)
}
public class ListItem<T: Diffable>: ListItemType, CustomDebugStringConvertible {
/// The cell reuse identifier.
public var reuseIdentifier: String
/// The unique identifier (used for the diffing algorithm).
public var diffIdentifier: String { return "\(reuseIdentifier)_\(model.diffIdentifier)" }
/// The *UICollectionView/UITableView* associated to this item.
public weak var referenceView: ListContainerView?
/// The actual model object.
public var model: T
/// A opaque pointer to the model associated to this row.
public var modelRef: Any? { return self.model }
/// A textual representation of this instance, suitable for debugging.
public var debugDescription: String { return self.diffIdentifier }
/// The configuration block applied to the target cell.
public var cellConfiguration: ((ListViewCell, T) -> Void)?
#if os(iOS)
public init<V: PrototypeViewCell>(
type: V.Type,
container: ListContainerView,
reuseIdentifer: String = String(describing: V.self),
model: T,
configurationClosure: ((V, T) -> Void)? = nil
) {
// Registers the prototype cell if necessary.
if !Prototypes.isPrototypeCellRegistered(reuseIdentifer) {
let cell = V(reuseIdentifier: reuseIdentifer)
Prototypes.registerPrototypeCell(reuseIdentifer, cell: cell)
}
self.reuseIdentifier = reuseIdentifer
if let closure = configurationClosure {
self.cellConfiguration = { cell, type in return closure(cell as! V, type) }
}
self.referenceView = container
self.model = model
self.registerReferenceView(with: type)
}
#endif
public init<V: ListViewCell>(
type: V.Type,
container: ListContainerView? = nil,
reuseIdentifer: String = String(describing: V.self),
id: String? = nil,
model: T,
configurationClosure: ((V, T) -> Void)? = nil
) {
self.reuseIdentifier = reuseIdentifer
if let closure = configurationClosure {
self.cellConfiguration = { cell, type in return closure(cell as! V, type) }
}
self.referenceView = container
self.model = model
self.registerReferenceView(with: type)
}
private func registerReferenceView(with cellClass: AnyClass) {
#if os(iOS)
if let tableView = self.referenceView as? UITableView {
tableView.register(cellClass, forCellReuseIdentifier: self.reuseIdentifier)
}
if let collectionView = self.referenceView as? UICollectionView {
collectionView.register(cellClass, forCellWithReuseIdentifier: self.reuseIdentifier)
}
#endif
}
/// Bind the cell passed as argument to this data item.
public func configure(cell: ListViewCell) {
self.cellConfiguration?(cell, self.model)
}
}