This repository has been archived by the owner on Dec 26, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathUICollectionView+NSFetchedResultsController.m
227 lines (171 loc) · 7.4 KB
/
UICollectionView+NSFetchedResultsController.m
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//
// UICollectionView+NSFetchedResultsController.m
// Radiant Tap Essentials
//
// Created by Aleksandar Vacić on 26.9.13.
// Copyright (c) 2013. Radiant Tap. All rights reserved.
//
#import "UICollectionView+NSFetchedResultsController.h"
#import <objc/runtime.h>
@implementation UICollectionView (NSFetchedResultsController)
- (void)addChangeForSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert: {
[self.insertedSectionIndexes addIndex:sectionIndex];
break;
}
case NSFetchedResultsChangeDelete: {
[self.deletedSectionIndexes addIndex:sectionIndex];
// since we are deleting entire section,
// remove items scheduled to be deleted/updated from this same section
NSMutableArray *indexPathsInSection = [NSMutableArray array];
//
for (NSIndexPath *indexPath in self.deletedItemIndexPaths) {
if (indexPath.section == sectionIndex) {
[indexPathsInSection addObject:indexPath];
}
}
[self.deletedItemIndexPaths removeObjectsInArray:indexPathsInSection];
//
[indexPathsInSection removeAllObjects];
for (NSIndexPath *indexPath in self.updatedItemIndexPaths) {
if (indexPath.section == sectionIndex) {
[indexPathsInSection addObject:indexPath];
}
}
[self.updatedItemIndexPaths removeObjectsInArray:indexPathsInSection];
break;
}
default:
break;
}
}
- (void)addChangeForObjectAtIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
if (type == NSFetchedResultsChangeInsert) {
if ([self.insertedSectionIndexes containsIndex:newIndexPath.section]) {
// If we've already been told that we're adding a section for this inserted row we skip it since it will handled by the section insertion.
return;
}
[self.insertedItemIndexPaths addObject:newIndexPath];
} else if (type == NSFetchedResultsChangeDelete) {
if ([self.deletedSectionIndexes containsIndex:indexPath.section]) {
// If we've already been told that we're deleting a section for this deleted row we skip it since it will handled by the section deletion.
return;
}
[self.deletedItemIndexPaths addObject:indexPath];
} else if (type == NSFetchedResultsChangeMove) {
if ([self.insertedSectionIndexes containsIndex:newIndexPath.section] == NO) {
[self.insertedItemIndexPaths addObject:newIndexPath];
}
if ([self.deletedSectionIndexes containsIndex:indexPath.section] == NO) {
[self.deletedItemIndexPaths addObject:indexPath];
}
} else if (type == NSFetchedResultsChangeUpdate) {
if ([self.deletedSectionIndexes containsIndex:indexPath.section] || [self.deletedItemIndexPaths containsObject:indexPath]) {
// If we've already been told that we're deleting a section for this deleted row we skip it since it will handled by the section deletion.
return;
}
if ([self.updatedItemIndexPaths containsObject:indexPath] == NO)
[self.updatedItemIndexPaths addObject:indexPath];
}
}
/*
NSFetchedResultsChangeInsert = 1,
NSFetchedResultsChangeDelete = 2,
NSFetchedResultsChangeMove = 3,
NSFetchedResultsChangeUpdate = 4
*/
- (void)commitChanges {
if (!self) return;
if (self.window == nil) {
[self clearChanges];
[self reloadData];
} else { // BIG
NSInteger totalChanges = [self.deletedSectionIndexes count] +
[self.insertedSectionIndexes count] +
[self.deletedItemIndexPaths count] +
[self.insertedItemIndexPaths count] +
[self.updatedItemIndexPaths count];
if (totalChanges > 50) {
[self clearChanges];
[self reloadData];
return;
}
[self performBatchUpdates:^{
[self deleteSections:self.deletedSectionIndexes];
[self insertSections:self.insertedSectionIndexes];
[self deleteItemsAtIndexPaths:self.deletedItemIndexPaths];
[self insertItemsAtIndexPaths:self.insertedItemIndexPaths];
[self reloadItemsAtIndexPaths:self.updatedItemIndexPaths];
} completion:^(BOOL finished) {
[self clearChanges];
}];
} //BIG else
}
- (void)clearChanges {
self.insertedSectionIndexes = nil;
self.deletedSectionIndexes = nil;
self.deletedItemIndexPaths = nil;
self.insertedItemIndexPaths = nil;
self.updatedItemIndexPaths = nil;
}
#pragma mark - Overridden getters
/**
* Lazily instantiate these collections.
*/
- (NSMutableIndexSet *)deletedSectionIndexes {
NSMutableIndexSet *_deletedSectionIndexes = objc_getAssociatedObject(self, @selector(deletedSectionIndexes));
if (_deletedSectionIndexes == nil) {
_deletedSectionIndexes = [[NSMutableIndexSet alloc] init];
objc_setAssociatedObject(self, @selector(deletedSectionIndexes), _deletedSectionIndexes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _deletedSectionIndexes;
}
- (void)setDeletedSectionIndexes:(NSMutableIndexSet *)deletedSectionIndexes {
objc_setAssociatedObject(self, @selector(deletedSectionIndexes), deletedSectionIndexes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableIndexSet *)insertedSectionIndexes {
NSMutableIndexSet *_insertedSectionIndexes = objc_getAssociatedObject(self, @selector(insertedSectionIndexes));
if (_insertedSectionIndexes == nil) {
_insertedSectionIndexes = [[NSMutableIndexSet alloc] init];
objc_setAssociatedObject(self, @selector(insertedSectionIndexes), _insertedSectionIndexes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _insertedSectionIndexes;
}
- (void)setInsertedSectionIndexes:(NSMutableIndexSet *)insertedSectionIndexes {
objc_setAssociatedObject(self, @selector(insertedSectionIndexes), insertedSectionIndexes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableArray *)deletedItemIndexPaths {
NSMutableArray *_deletedItemIndexPaths = objc_getAssociatedObject(self, @selector(deletedItemIndexPaths));
if (_deletedItemIndexPaths == nil) {
_deletedItemIndexPaths = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, @selector(deletedItemIndexPaths), _deletedItemIndexPaths, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _deletedItemIndexPaths;
}
- (void)setDeletedItemIndexPaths:(NSMutableArray *)deletedItemIndexPaths {
objc_setAssociatedObject(self, @selector(deletedItemIndexPaths), deletedItemIndexPaths, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableArray *)insertedItemIndexPaths {
NSMutableArray *_insertedItemIndexPaths = objc_getAssociatedObject(self, @selector(insertedItemIndexPaths));
if (_insertedItemIndexPaths == nil) {
_insertedItemIndexPaths = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, @selector(insertedItemIndexPaths), _insertedItemIndexPaths, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _insertedItemIndexPaths;
}
- (void)setInsertedItemIndexPaths:(NSMutableArray *)insertedItemIndexPaths {
objc_setAssociatedObject(self, @selector(insertedItemIndexPaths), insertedItemIndexPaths, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableArray *)updatedItemIndexPaths {
NSMutableArray *_updatedItemIndexPaths = objc_getAssociatedObject(self, @selector(updatedItemIndexPaths));
if (_updatedItemIndexPaths == nil) {
_updatedItemIndexPaths = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, @selector(updatedItemIndexPaths), _updatedItemIndexPaths, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _updatedItemIndexPaths;
}
- (void)setUpdatedItemIndexPaths:(NSMutableArray *)updatedItemIndexPaths {
objc_setAssociatedObject(self, @selector(updatedItemIndexPaths), updatedItemIndexPaths, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end