-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFilteredFirestoreCollectionViewDataSource.swift
More file actions
149 lines (125 loc) · 5.5 KB
/
FilteredFirestoreCollectionViewDataSource.swift
File metadata and controls
149 lines (125 loc) · 5.5 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//
// FilteredFirestoreCollectionViewDataSource.swift
// Mangos
//
// Created by Rafael Matsunaga on 27/09/18.
// Copyright © 2018 Priced. All rights reserved.
//
import Foundation
import FirebaseUI
import Firebase
class FilteredFirestoreCollectionViewDataSource:NSObject, UICollectionViewDataSource, FilteredBatchedArrayDelegate {
var collectionView:UICollectionView?
var collection:FilteredBatchedArray?
var populateCellatIndexPath:(UICollectionView, IndexPath, DocumentSnapshot) -> UICollectionViewCell
var queryErrorHandler:((Error)->Void)?
var count:Int {
get {
return self.collection?.items.count ?? 0
}
}
var items:[DocumentSnapshot]? {
get {
return self.collection?.items
}
}
var query:Query? {
get {
return self.collection?.query
}
}
init(query: Query, collectionView: UICollectionView, populateCell: @escaping (UICollectionView, IndexPath, DocumentSnapshot) -> UICollectionViewCell) {
self.populateCellatIndexPath = populateCell
super.init()
self.collection = FilteredBatchedArray(query: query, delegate: self)
}
func snapshotAtIndex(index:Int)->DocumentSnapshot? {
return self.collection?.items[index]
}
func bindToView(view:UICollectionView) {
self.collectionView = view
view.dataSource = self
self.collection?.observeQuery()
}
func unbind() {
self.collectionView?.dataSource = nil
self.collectionView = nil
self.collection?.stopObserving()
}
func setQuery(query:Query) {
self.collection?.setQuery(query: query)
}
func setFilter(_ filter:@escaping (DocumentSnapshot) throws -> Bool) {
self.collection?.setFilter(filter)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.collection?.items.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let snap = self.collection?.items[indexPath.item]
let cell = self.populateCellatIndexPath(collectionView, indexPath, snap!)
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func batchedArray(_ array: FilteredBatchedArray, didUpdateWith diff: FUISnapshotArrayDiff<DocumentSnapshot>) {
self.collectionView?.performBatchUpdates({
// delete
var deletedIndexPaths = [IndexPath]()
for index in diff.deletedIndexes {
let deletedIndexPath = IndexPath(item: index.intValue, section: 0)
deletedIndexPaths.append(deletedIndexPath)
}
self.collectionView?.deleteItems(at: deletedIndexPaths)
// change
var changedIndexPaths = [IndexPath]()
for index in diff.changedIndexes {
let changedIndexPath = IndexPath(item: index.intValue, section: 0)
changedIndexPaths.append(changedIndexPath)
}
// Use a delete and insert instead of a reload. See
// https://stackoverflow.com/questions/42147822/uicollectionview-batchupdate-edge-case-fails
self.collectionView?.deleteItems(at: changedIndexPaths)
self.collectionView?.insertItems(at: changedIndexPaths)
// move
for i in 0 ..< diff.movedInitialIndexes.count {
let initialIndex = diff.movedInitialIndexes[i].intValue
let finalIndex = diff.movedResultIndexes[i].intValue
let initialPath = IndexPath(item: initialIndex, section: 0)
let finalPath = IndexPath(item: finalIndex, section: 0)
self.collectionView?.moveItem(at: initialPath, to: finalPath)
}
// insert
var insertedIndexPaths = [IndexPath]()
for index in diff.insertedIndexes {
let insertedIndexPath = IndexPath(item: index.intValue, section: 0)
insertedIndexPaths.append(insertedIndexPath)
}
self.collectionView?.insertItems(at: insertedIndexPaths)
}, completion: { finished in
// Reload paths that have been moved.
var movedIndexPaths:[IndexPath] = [IndexPath]()
for index in diff.movedResultIndexes {
let movedIndexPath = IndexPath(item: index.intValue, section: 0)
movedIndexPaths.append(movedIndexPath)
}
self.collectionView?.reloadItems(at: movedIndexPaths)
})
}
func batchedArray(_ array: FilteredBatchedArray, queryDidFailWithError error: Error) {
if self.queryErrorHandler != nil {
self.queryErrorHandler!(error)
} else {
print(String(format:"%@ Unhandled Firestore error: %@. Set the queryErrorHandler property to debug.",
self, error.localizedDescription))
}
}
}
extension UICollectionView {
func bind(toFirestoreQuery:Query, populateCell:@escaping (UICollectionView, IndexPath, DocumentSnapshot) -> UICollectionViewCell)->FilteredFirestoreCollectionViewDataSource {
let dataSource = FilteredFirestoreCollectionViewDataSource(query: toFirestoreQuery, collectionView: self, populateCell: populateCell)
dataSource.bindToView(view: self)
return dataSource
}
}