Skip to content
This repository was archived by the owner on Jan 16, 2021. It is now read-only.

Commit 9f6e4e5

Browse files
committed
Merge pull request #98 from richardjrossiii/master
Added support for deletion from PFQueryTableViewController and PFQueryCollectionViewController.
2 parents 85a8d83 + 4105a44 commit 9f6e4e5

File tree

14 files changed

+933
-15
lines changed

14 files changed

+933
-15
lines changed

ParseUI.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@
116116
A5375DF534FF03442906BCAC /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B91892E5A1364B4A9F064902 /* Pods.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
117117
AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; };
118118
BD1FB4C4DFB833BFFD3E209A /* (null) in Frameworks */ = {isa = PBXBuildFile; };
119+
F57F3D231B0C03D40087F60B /* DeletionCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F57F3D201B0C03C90087F60B /* DeletionCollectionViewController.m */; };
120+
F57F3D241B0C03DB0087F60B /* DeletionTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F57F3D1C1B0C03BA0087F60B /* DeletionTableViewController.m */; };
121+
F57F3D271B0C050C0087F60B /* DeletionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F57F3D251B0C04EF0087F60B /* DeletionTableViewController.swift */; };
122+
F57F3D291B0C05280087F60B /* DeletionCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F57F3D281B0C05280087F60B /* DeletionCollectionViewController.swift */; };
119123
/* End PBXBuildFile section */
120124

121125
/* Begin PBXFileReference section */
@@ -240,6 +244,12 @@
240244
B774A7483212431D2C034600 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
241245
B91892E5A1364B4A9F064902 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
242246
D2AAC07E0554694100DB518D /* ParseUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
247+
F57F3D1B1B0C03BA0087F60B /* DeletionTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeletionTableViewController.h; sourceTree = "<group>"; };
248+
F57F3D1C1B0C03BA0087F60B /* DeletionTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeletionTableViewController.m; sourceTree = "<group>"; };
249+
F57F3D1F1B0C03C90087F60B /* DeletionCollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeletionCollectionViewController.h; sourceTree = "<group>"; };
250+
F57F3D201B0C03C90087F60B /* DeletionCollectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeletionCollectionViewController.m; sourceTree = "<group>"; };
251+
F57F3D251B0C04EF0087F60B /* DeletionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletionTableViewController.swift; sourceTree = "<group>"; };
252+
F57F3D281B0C05280087F60B /* DeletionCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletionCollectionViewController.swift; sourceTree = "<group>"; };
243253
/* End PBXFileReference section */
244254

245255
/* Begin PBXFrameworksBuildPhase section */
@@ -467,6 +477,8 @@
467477
81472FA11A1AB37500FD6EED /* QueryTableViewController */ = {
468478
isa = PBXGroup;
469479
children = (
480+
F57F3D1B1B0C03BA0087F60B /* DeletionTableViewController.h */,
481+
F57F3D1C1B0C03BA0087F60B /* DeletionTableViewController.m */,
470482
81472F971A1AB37500FD6EED /* SimpleTableViewController.h */,
471483
81472F981A1AB37500FD6EED /* SimpleTableViewController.m */,
472484
81472F991A1AB37500FD6EED /* PaginatedTableViewController.h */,
@@ -558,6 +570,8 @@
558570
81C5993C1A64344800F574E8 /* QueryCollectionViewController */ = {
559571
isa = PBXGroup;
560572
children = (
573+
F57F3D1F1B0C03C90087F60B /* DeletionCollectionViewController.h */,
574+
F57F3D201B0C03C90087F60B /* DeletionCollectionViewController.m */,
561575
81C5993D1A64346000F574E8 /* SimpleCollectionViewController.h */,
562576
81C5993E1A64346000F574E8 /* SimpleCollectionViewController.m */,
563577
81C599401A6454C900F574E8 /* PaginatedCollectionViewController.h */,
@@ -685,6 +699,7 @@
685699
81FC6B571A9D1BFC00104E45 /* QueryTableViewController */ = {
686700
isa = PBXGroup;
687701
children = (
702+
F57F3D251B0C04EF0087F60B /* DeletionTableViewController.swift */,
688703
81FC6B5B1A9D1BFC00104E45 /* SimpleTableViewController.swift */,
689704
81FC6B591A9D1BFC00104E45 /* PaginatedTableViewController.swift */,
690705
81FC6B5A1A9D1BFC00104E45 /* SectionedTableViewController.swift */,
@@ -698,6 +713,7 @@
698713
81FC6B661A9D1CE900104E45 /* QueryCollectionViewController */ = {
699714
isa = PBXGroup;
700715
children = (
716+
F57F3D281B0C05280087F60B /* DeletionCollectionViewController.swift */,
701717
81FC6B691A9D1CE900104E45 /* SimpleCollectionViewController.swift */,
702718
81FC6B671A9D1CE900104E45 /* PaginatedCollectionViewController.swift */,
703719
81FC6B681A9D1CE900104E45 /* SectionedCollectionViewController.swift */,
@@ -1078,7 +1094,9 @@
10781094
81FC6B601A9D1BFC00104E45 /* SectionedTableViewController.swift in Sources */,
10791095
81FC6B5F1A9D1BFC00104E45 /* PaginatedTableViewController.swift in Sources */,
10801096
81FC6B611A9D1BFC00104E45 /* SimpleTableViewController.swift in Sources */,
1097+
F57F3D291B0C05280087F60B /* DeletionCollectionViewController.swift in Sources */,
10811098
81FC6B6E1A9D1CE900104E45 /* SimpleCollectionViewController.swift in Sources */,
1099+
F57F3D271B0C050C0087F60B /* DeletionTableViewController.swift in Sources */,
10821100
81FC6B6D1A9D1CE900104E45 /* SectionedCollectionViewController.swift in Sources */,
10831101
81FC6B561A9D1ADB00104E45 /* CustomSignUpViewController.swift in Sources */,
10841102
81FC6B621A9D1BFC00104E45 /* StoryboardTableViewController.swift in Sources */,
@@ -1103,8 +1121,10 @@
11031121
81472FB41A1AB37500FD6EED /* CustomLogInViewController.m in Sources */,
11041122
81472FB91A1AB37500FD6EED /* CustomProductTableViewController.m in Sources */,
11051123
819A4B3A1A6808EA00D01241 /* SubtitleImageCollectionViewController.m in Sources */,
1124+
F57F3D241B0C03DB0087F60B /* DeletionTableViewController.m in Sources */,
11061125
812E5C041A7A8EFB000FBDE1 /* StoryboardCollectionViewController.m in Sources */,
11071126
81472FB51A1AB37500FD6EED /* SimpleTableViewController.m in Sources */,
1127+
F57F3D231B0C03D40087F60B /* DeletionCollectionViewController.m in Sources */,
11081128
81472FB61A1AB37500FD6EED /* PaginatedTableViewController.m in Sources */,
11091129
81C8D9BD1A890BCA007B8DCF /* StoryboardTableViewController.m in Sources */,
11101130
81472FB71A1AB37500FD6EED /* SectionedTableViewController.m in Sources */,

ParseUI/Classes/QueryCollectionViewController/PFQueryCollectionViewController.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
PFUI_ASSUME_NONNULL_BEGIN
2727

28+
@class BFTask;
2829
@class PFCollectionViewCell;
2930
@class PFObject;
3031
@class PFQuery;
@@ -139,23 +140,37 @@ PFUI_ASSUME_NONNULL_BEGIN
139140
*/
140141
- (PFUI_NULLABLE PFObject *)objectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath;
141142

143+
/*!
144+
@abstract Removes an object at the specified index path, animated.
145+
*/
146+
- (void)removeObjectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath;
147+
148+
/*!
149+
@abstract Removes all objects at the specified index paths, animated.
150+
*/
151+
- (void)removeObjectsAtIndexPaths:(PFUI_NULLABLE NSArray *)indexes;
152+
142153
///--------------------------------------
143154
/// @name Loading Data
144155
///--------------------------------------
145156

146157
/*!
147158
@abstract Clears the collection view and loads the first page of objects.
159+
160+
@returns An awaitable task that completes when the reload succeeds
148161
*/
149-
- (void)loadObjects;
162+
- (BFTask *)loadObjects;
150163

151164
/*!
152165
@abstract Loads the objects of the <parseClassName> at the specified page and appends it to the
153166
objects already loaded and refreshes the collection.
154167
155168
@param page The page of objects to load.
156169
@param clear Whether to clear the collection view after receiving the objects.
170+
171+
@returns An awaitable task that completes when the reload succeeds
157172
*/
158-
- (void)loadObjects:(NSInteger)page clear:(BOOL)clear;
173+
- (BFTask *)loadObjects:(NSInteger)page clear:(BOOL)clear;
159174

160175
/*!
161176
@abstract Loads the next page of objects, appends to table, and refreshes.

ParseUI/Classes/QueryCollectionViewController/PFQueryCollectionViewController.m

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
#import "PFQueryCollectionViewController.h"
2323

24+
#import <Bolts/BFTask.h>
25+
#import <Bolts/BFTaskCompletionSource.h>
26+
2427
#import <Parse/Parse.h>
2528

2629
#import "PFActivityIndicatorCollectionReusableView.h"
@@ -164,17 +167,71 @@ - (PFObject *)objectAtIndexPath:(NSIndexPath *)indexPath {
164167
return self.objects[indexPath.row];
165168
}
166169

170+
#pragma mark -
171+
#pragma mark Removing Objects
172+
173+
- (void)removeObjectAtIndexPath:(NSIndexPath *)indexPath {
174+
[self removeObjectsAtIndexPaths:@[ indexPath ]];
175+
}
176+
177+
- (void)removeObjectsAtIndexPaths:(NSArray *)indexPaths {
178+
if (indexPaths.count == 0) {
179+
return;
180+
}
181+
182+
// We need the contents as both an index set and a list of index paths.
183+
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
184+
185+
for (NSIndexPath *indexPath in indexPaths) {
186+
if (indexPath.section != 0) {
187+
[NSException raise:NSRangeException format:@"Index Path section %lu out of range!", (long)indexPath.section];
188+
}
189+
190+
if (indexPath.row >= self.objects.count) {
191+
[NSException raise:NSRangeException format:@"Index Path row %lu out of range!", (long)indexPath.row];
192+
}
193+
194+
[indexes addIndex:indexPath.row];
195+
}
196+
197+
BFContinuationBlock deletionHandlerBlock = ^id (BFTask *task) {
198+
self.refreshControl.enabled = YES;
199+
200+
if (task.error) {
201+
[self _handleDeletionError:task.error];
202+
}
203+
204+
return nil;
205+
};
206+
207+
NSMutableArray *allDeletionTasks = [NSMutableArray arrayWithCapacity:indexes.count];
208+
NSArray *objectsToRemove = [self.objects objectsAtIndexes:indexes];
209+
210+
// Remove the contents from our local cache so we can give the user immediate feedback.
211+
[_mutableObjects removeObjectsInArray:objectsToRemove];
212+
[self.collectionView deleteItemsAtIndexPaths:indexPaths];
213+
214+
for (id obj in objectsToRemove) {
215+
[allDeletionTasks addObject:[obj deleteInBackground]];
216+
}
217+
218+
[[BFTask taskForCompletionOfAllTasks:allDeletionTasks]
219+
continueWithBlock:deletionHandlerBlock];
220+
}
221+
167222
#pragma mark -
168223
#pragma mark Loading Data
169224

170-
- (void)loadObjects {
171-
[self loadObjects:0 clear:YES];
225+
- (BFTask *)loadObjects {
226+
return [self loadObjects:0 clear:YES];
172227
}
173228

174-
- (void)loadObjects:(NSInteger)page clear:(BOOL)clear {
229+
- (BFTask *)loadObjects:(NSInteger)page clear:(BOOL)clear {
175230
self.loading = YES;
176231
[self objectsWillLoad];
177232

233+
BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];
234+
178235
PFQuery *query = [self queryForCollection];
179236
[self _alterQuery:query forLoadingPage:page];
180237
[query findObjectsInBackgroundWithBlock:^(NSArray *foundObjects, NSError *error) {
@@ -197,15 +254,18 @@ - (void)loadObjects:(NSInteger)page clear:(BOOL)clear {
197254
if (clear) {
198255
[_mutableObjects removeAllObjects];
199256
}
200-
[_mutableObjects addObjectsFromArray:foundObjects];
201257

202-
// Reload the table data
258+
[_mutableObjects addObjectsFromArray:foundObjects];
203259
[self.collectionView reloadData];
204260
}
205261

206262
[self objectsDidLoad:error];
207263
[self.refreshControl endRefreshing];
264+
265+
[source setError:error];
208266
}];
267+
268+
return source.task;
209269
}
210270

211271
- (void)loadNextPage {
@@ -322,6 +382,38 @@ - (NSIndexPath *)_indexPathForPaginationReusableView {
322382
return [NSIndexPath indexPathForItem:0 inSection:[self numberOfSectionsInCollectionView:self.collectionView] - 1];
323383
}
324384

385+
#pragma mark -
386+
#pragma mark Error handling
387+
388+
- (void)_handleDeletionError:(NSError *)error {
389+
// Fully reload on error.
390+
[self loadObjects];
391+
392+
NSString *errorMessage = [NSString stringWithFormat:@"%@: \"%@\"",
393+
NSLocalizedString(@"Error occurred during deletion", @"Error occurred during deletion"),
394+
error.localizedDescription];
395+
396+
if ([UIAlertController class]) {
397+
UIAlertController *errorController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Error", @"Error")
398+
message:errorMessage
399+
preferredStyle:UIAlertControllerStyleAlert];
400+
401+
[errorController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
402+
style:UIAlertActionStyleCancel
403+
handler:nil]];
404+
405+
[self presentViewController:errorController animated:YES completion:nil];
406+
} else {
407+
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"Error")
408+
message:errorMessage
409+
delegate:nil
410+
cancelButtonTitle:NSLocalizedString(@"OK", @"OK")
411+
otherButtonTitles:nil];
412+
413+
[alertView show];
414+
}
415+
}
416+
325417
#pragma mark -
326418
#pragma mark Actions
327419

ParseUI/Classes/QueryTableViewController/PFQueryTableViewController.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
PFUI_ASSUME_NONNULL_BEGIN
2727

28+
@class BFTask;
2829
@class PFObject;
2930
@class PFQuery;
3031
@class PFTableViewCell;
@@ -161,24 +162,48 @@ PFUI_ASSUME_NONNULL_BEGIN
161162
*/
162163
- (PFUI_NULLABLE PFObject *)objectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath;
163164

165+
/*!
166+
@abstract Removes an object at the specified index path, animated.
167+
*/
168+
- (void)removeObjectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath;
169+
170+
/*!
171+
@abstract Removes an object at the specified index path, with or without animation.
172+
*/
173+
- (void)removeObjectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath animated:(BOOL)animated;
174+
175+
/*!
176+
@abstract Removes all objects at the specified index paths, animated.
177+
*/
178+
- (void)removeObjectsAtIndexPaths:(PFUI_NULLABLE NSArray *)indexes;
179+
180+
/*!
181+
@abstract Removes all objects at the specified index paths, with or without animation.
182+
*/
183+
- (void)removeObjectsAtIndexPaths:(PFUI_NULLABLE NSArray *)indexes animated:(BOOL)animated;
184+
164185
/*!
165186
@abstract Clears the table of all objects.
166187
*/
167188
- (void)clear;
168189

169190
/*!
170191
@abstract Clears the table and loads the first page of objects.
192+
193+
@returns An awaitable task that completes when the reload succeeds
171194
*/
172-
- (void)loadObjects;
195+
- (BFTask *)loadObjects;
173196

174197
/*!
175198
@abstract Loads the objects of the className at the specified page and appends it to the
176199
objects already loaded and refreshes the table.
177200
178201
@param page The page of objects to load.
179-
@param clear Whether to clear the table after receiving the objects.
202+
@param clear Whether to clear the table after receiving the objects
203+
204+
@returns An awaitable task that completes when the reload succeeds
180205
*/
181-
- (void)loadObjects:(NSInteger)page clear:(BOOL)clear;
206+
- (BFTask *)loadObjects:(NSInteger)page clear:(BOOL)clear;
182207

183208
/*!
184209
@abstract Loads the next page of objects, appends to table, and refreshes.

0 commit comments

Comments
 (0)