9
9
10
10
#import " PFObjectBatchController.h"
11
11
12
+ #import < Bolts/Bolts.h>
13
+
12
14
#import " BFTask+Private.h"
13
15
#import " PFAssert.h"
14
16
#import " PFCommandResult.h"
19
21
#import " PFObjectPrivate.h"
20
22
#import " PFQueryPrivate.h"
21
23
#import " PFRESTQueryCommand.h"
24
+ #import " PFRESTObjectCommand.h"
25
+ #import " PFRESTObjectBatchCommand.h"
22
26
23
27
@implementation PFObjectBatchController
24
28
@@ -98,10 +102,85 @@ - (BFTask *)_processFetchResultAsync:(NSDictionary *)result forObjects:(NSArray
98
102
}];
99
103
}
100
104
105
+ // /--------------------------------------
106
+ #pragma mark - Delete
107
+ // /--------------------------------------
108
+
109
+ - (BFTask *)deleteObjectsAsync : (NSArray *)objects withSessionToken : (NSString *)sessionToken {
110
+ if (objects.count == 0 ) {
111
+ return [BFTask taskWithResult: objects];
112
+ }
113
+
114
+ @weakify (self);
115
+ return [[BFTask taskFromExecutor: [BFExecutor defaultPriorityBackgroundExecutor ] withBlock: ^id {
116
+ @strongify (self);
117
+ NSArray *objectBatches = [PFInternalUtils arrayBySplittingArray: objects
118
+ withMaximumComponentsPerSegment: PFRESTObjectBatchCommandSubcommandsLimit];
119
+ NSMutableArray *tasks = [NSMutableArray arrayWithCapacity: objectBatches.count];
120
+ for (NSArray *batch in objectBatches) {
121
+ PFRESTCommand *command = [self _deleteCommandForObjects: batch withSessionToken: sessionToken];
122
+ BFTask *task = [[self .dataSource.commandRunner runCommandAsync: command
123
+ withOptions: PFCommandRunningOptionRetryIfFailed] continueWithSuccessBlock: ^id (BFTask *task) {
124
+ PFCommandResult *result = task.result ;
125
+ return [self _processDeleteResultsAsync: [result result ] forObjects: batch];
126
+ }];
127
+ [tasks addObject: task];
128
+ }
129
+ return [[BFTask taskForCompletionOfAllTasks: tasks] continueWithBlock: ^id (BFTask *task) {
130
+ NSError *taskError = task.error ;
131
+ if (taskError && [taskError.domain isEqualToString: BFTaskErrorDomain]) {
132
+ NSArray *taskErrors = taskError.userInfo [@" errors" ];
133
+ NSMutableArray *errors = [NSMutableArray array ];
134
+ for (NSError *error in taskErrors) {
135
+ if ([error.domain isEqualToString: BFTaskErrorDomain]) {
136
+ [errors addObjectsFromArray: error.userInfo[@" errors" ]];
137
+ } else {
138
+ [errors addObject: error];
139
+ }
140
+ }
141
+ return [BFTask taskWithError: [NSError errorWithDomain: BFTaskErrorDomain
142
+ code: kBFMultipleErrorsError
143
+ userInfo: @{ @" errors" : errors }]];
144
+ }
145
+ return task;
146
+ }];
147
+ }] continueWithSuccessResult: objects];
148
+ }
149
+
150
+ - (PFRESTCommand *)_deleteCommandForObjects : (NSArray *)objects withSessionToken : (NSString *)sessionToken {
151
+ NSMutableArray *commands = [NSMutableArray arrayWithCapacity: objects.count];
152
+ for (PFObject *object in objects) {
153
+ PFRESTCommand *deleteCommand = [PFRESTObjectCommand deleteObjectCommandForObjectState: object._state
154
+ withSessionToken: sessionToken];
155
+ [commands addObject: deleteCommand];
156
+ }
157
+ return [PFRESTObjectBatchCommand batchCommandWithCommands: commands sessionToken: sessionToken];
158
+ }
159
+
160
+ - (BFTask *)_processDeleteResultsAsync : (NSArray *)results forObjects : (NSArray *)objects {
161
+ NSMutableArray *tasks = [NSMutableArray arrayWithCapacity: results.count];
162
+ [results enumerateObjectsUsingBlock: ^(NSDictionary *result, NSUInteger idx, BOOL *stop) {
163
+ PFObject *object = objects[idx];
164
+ NSDictionary *errorResult = result[@" error" ];
165
+ NSDictionary *successResult = result[@" success" ];
166
+
167
+ id <PFObjectControlling> controller = [[object class ] objectController ];
168
+ BFTask *task = [controller processDeleteResultAsync: successResult forObject: object];
169
+ if (errorResult) {
170
+ task = [task continueWithBlock: ^id (BFTask *task) {
171
+ return [BFTask taskWithError: [PFErrorUtilities errorFromResult: errorResult]];
172
+ }];
173
+ }
174
+ [tasks addObject: task];
175
+ }];
176
+ return [BFTask taskForCompletionOfAllTasks: tasks];
177
+ }
178
+
101
179
// /--------------------------------------
102
180
#pragma mark - Utilities
103
181
// /--------------------------------------
104
182
183
+ // TODO: (nlutsenko) Convert to use `uniqueObjectsArrayFromArray:usingFilter:`
105
184
+ (NSArray *)uniqueObjectsArrayFromArray : (NSArray *)objects omitObjectsWithData : (BOOL )omitFetched {
106
185
if (objects.count == 0 ) {
107
186
return objects;
@@ -115,6 +194,7 @@ + (NSArray *)uniqueObjectsArrayFromArray:(NSArray *)objects omitObjectsWithData:
115
194
continue ;
116
195
}
117
196
197
+ // TODO: (nlutsenko) Convert to using errors instead of assertions.
118
198
PFParameterAssert ([className isEqualToString: object.parseClassName],
119
199
@" All object should be in the same class." );
120
200
PFParameterAssert (object.objectId != nil ,
@@ -126,4 +206,24 @@ + (NSArray *)uniqueObjectsArrayFromArray:(NSArray *)objects omitObjectsWithData:
126
206
return [set allObjects ];
127
207
}
128
208
209
+ + (NSArray *)uniqueObjectsArrayFromArray : (NSArray *)objects usingFilter : (BOOL (^)(PFObject *object))filter {
210
+ if (objects.count == 0 ) {
211
+ return objects;
212
+ }
213
+
214
+ NSMutableDictionary *uniqueObjects = [NSMutableDictionary dictionary ];
215
+ for (PFObject *object in objects) {
216
+ if (!filter (object)) {
217
+ continue ;
218
+ }
219
+
220
+ // Use stringWithFormat: in case objectId or parseClassName are nil.
221
+ NSString *objectIdentifier = [NSString stringWithFormat: @" %@%@ " , object.parseClassName, object.objectId];
222
+ if (!uniqueObjects[objectIdentifier]) {
223
+ uniqueObjects[objectIdentifier] = object;
224
+ }
225
+ }
226
+ return [uniqueObjects allValues ];
227
+ }
228
+
129
229
@end
0 commit comments