I am using the following to delete objects using RestKit (0.23.1):
[self.objectManager deleteObject:myObject path:path parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"success deleting myObject");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"failure deleting myObject");
}];
This does create the correct DELETE request and the server returns a 200 status code. However, the local data is not deleted from Core Data. If I do a fetch for the deleted object after the success block above is fired, the fetch returns the object that should be deleted.
The documentation reads:
RKManagedObjectRequestOperation adds special behavior to DELETE requests. Upon retrieving a successful (2xx status code) response for a DELETE, the operation will invoke deleteObject: with the operations targetObject on the managed object context. This will delete the target object from the local store in conjunction the successfully deleted remote representation.
Doing a little spelunking it looks like -[RKManagedObjectRequestOperation deleteTargetObject:]
is not being called. It seems that it should be called by -[RKManagedObjectRequestOperation willFinish]
.
It seems like there may be a logic error in the gating if statement in -[RKManagedObjectRequestOperation willFinish]
.
- (void)willFinish
{
NSMutableIndexSet *deleteableStatusCodes = [NSMutableIndexSet indexSet];
[deleteableStatusCodes addIndex:404]; // Not Found
[deleteableStatusCodes addIndex:410]; // Gone
if (self.error && self.targetObjectID
&& [[[self.HTTPRequestOperation.request HTTPMethod] uppercaseString] isEqualToString:@"DELETE"]
&& [deleteableStatusCodes containsIndex:self.HTTPRequestOperation.response.statusCode]) {
NSError *error = nil;
if (! [self deleteTargetObject:&error]) {
RKLogWarning(@"Secondary error encountered while attempting to delete target object in response to 404 (Not Found) or 410 (Gone) status code: %@", error);
self.error = error;
} else {
if (! [self saveContext:&error]) {
} else {
// All good, clear any errors
self.error = nil;
}
}
}
}
It seems like -[RKManagedObjectRequestOperation willFinish]
should be as follows:
- (void)willFinish
{
NSMutableIndexSet *deleteableStatusCodes = [NSMutableIndexSet indexSet];
[deleteableStatusCodes addIndex:404]; // Not Found
[deleteableStatusCodes addIndex:410]; // Gone
[deleteableStatusCodes addIndexes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
if (self.error == nil
&& self.targetObjectID
&& [[[self.HTTPRequestOperation.request HTTPMethod] uppercaseString] isEqualToString:@"DELETE"]
&& [deleteableStatusCodes containsIndex:self.HTTPRequestOperation.response.statusCode]) {
NSError *error = nil;
if (! [self deleteTargetObject:&error]) {
RKLogWarning(@"Secondary error encountered while attempting to delete target object in response to 404 (Not Found) or 410 (Gone) status code: %@", error);
self.error = error;
} else {
if (! [self saveContext:&error]) {
} else {
// All good, clear any errors
self.error = nil;
}
}
}
}
To summarize the changes, I added the successful status codes to the deleteableStatusCodes
index set and check to make sure that self.error
is equal to nil.
Is my logic change sound, or am I misunderstanding some RestKit convention here? It seems like my logic change aligns with the quoted statement from the documentation.
You're looking in the wrong place. See the line:
success = [weakSelf deleteTargetObject:&error];
In the performMappingOnResponseWithCompletionBlock:
method in RKManagedObjectRequestOperation
which checks for success status and deletes the object.
The code you have edited is to deal with error responses which, in a nice REST interface, mean the same thing as a DELETE success response.