Restkit - Wait for completion and stop all operation if something fails - restkit

I have a batch of requests that I build as follow:
for(int i = 0; i < count; i++)
{
RKObjectRequestOperation *operation = [objectManager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodPOST path:#"sync.json" parameters: nil];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
[objectManager enqueueObjectRequestOperation:operation];
[operation waitUntilFinished];
}
The code is supposed to stop and wait to every single operation before going on.
How can I stop or rather remove all queued operation if something goes wrong?
Maybe by using cancelAllObjectRequestOperationsWithMethod?
[EDIT]
In Restkit 0.20 maybe is better to use objectManager postObject:reqObj...

Related

Response 200OK but code enters the failure block in restkit

I have connected Charles to check the response of the call. The response header return 200OK but even then the code enters the failure block. Does it have to do anything with the way mapping is defined or is it some other trivial issue?
NSString *reviewsRequest = [NSString stringWithFormat:#"reviews/%#", reviewerId];
[MTAuthHandler refreshTokenIfExpired:^(id result, NSError *error) {
[MTRestkitManager instance].objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[[MTRestkitManager instance].objectManager getObjectsAtPath:reviewsRequest parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"success");
if (completion) {
completion(YES, nil);
}
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"failed");
if (completion) {
completion(NO, error);
}
}];
}];
The error message shows - NSLocalizedDescription=Expected status code in (400-499), got 200
Any pointers will be highly appreciated.

How to perform a DELETE request using RestKit (0.20)?

I'm trying to send a DELETE request using RestKit, but it seems that it is always sent as "GET". Here is my code:
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor
responseDescriptorWithMapping:[self objectMapping]
method:RKRequestMethodDELETE
pathPattern:nil
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[ responseDescriptor ]];
[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
[delegate onRequestSuccess:mappingResult.array];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"operation failed with error: %#", error);
[delegate onRequestError:operation message:error];
}];
[objectRequestOperation start];
I tried also using RKObjectManager:deleteObject, which does correctly send a DELETE request, but the response does not get mapped.
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:request.url];
[manager addResponseDescriptor:responseDescriptor];
[manager deleteObject:nil path:request.urlString parameters:nil
success:^(RKObjectRequestOperation *operation , RKMappingResult *mappingResult) {
Tag *tag = mappingResult.firstObject; // this is null, does not get mapped
} failure:^(RKObjectRequestOperation *operation , NSError *error) {
RKLogError(#"Error deleting tag %#, error: %#", tagId, error);
}];
If you're using RKObjectRequestOperation you need to configure the request yourself. It's GET because that is the default.
If you use RKObjectManager then you can use deleteObject instead which will do it for you.

Access Response Data in Success callback

Is there any way to access the response data in the success block for a request using the object manager?
[objectManager postObject:[User class] path:#"/users" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"success");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"failure");
}];
It seems like there should be some way to use the mapping or operation to get this information as maybe NSData or something.
You can get this info from the RKObjectRequestOperation *operation
operation.HTTPRequestOperation.response
operation.HTTPRequestOperation.responseData
operation.HTTPRequestOperation.responseString
try this
[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
// parse the response---
NSDictionary *myDic = [NSJSONSerialization JSONObjectWithData:operation.HTTPRequestOperation.responseData options:NSJSONReadingMutableLeaves error:nil];
NSLog(#"=======:%#",myDic);
NSLog(#"MY email============ %# ",[myDic objectForKey:#"Email"]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Operation failed with error: %#", error);
}];

How can I wait for result from geocodeAddressString iPhone

I know its something to do with locks or dispatch groups, but I just cant seem to code it...
I need to know if the address was a valid address before leaving the method. Currently the thread just overruns and returns TRUE. I've tried locks, dispatchers the works but can't seem to get it correct. Any help appreciated:
- (BOOL) checkAddressIsReal
{
__block BOOL result = TRUE;
// Lets Build the address
NSString *location = [NSString stringWithFormat:#" %# %#, %#, %#, %#", streetNumberText.text, streetNameText.text, townNameText.text, cityNameText.text, countryNameText.text];
// Put a pin on it if it is valid
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error) {
result = [placemarks count] != 0;
}];
return result;
}
The documentation says that CLGeocoder calls the completionHandler on the main thread. Since you are probably also calling your method from the main thread it cannot wait for the geocoder's answer without giving it the opportunity to deliver the result.
That would be done by polling the runloop, using some API as -[NSRunLoop runMode:beforeDate:].
The disadvantage is that depending on the mode this will also deliver events and fire timers while waiting for the result.
Just use block as parameter:
- (void) checkAddressIsRealWithComplectionHandler:(void (^)(BOOL result))complectionHandler
{
__block BOOL result = TRUE;
// Lets Build the address
NSString *location = [NSString stringWithFormat:#" %# %#, %#, %#, %#", streetNumberText.text, streetNameText.text, townNameText.text, cityNameText.text, countryNameText.text];
// Put a pin on it if it is valid
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error) {
result = [placemarks count] != 0;
complectionHandler(result);
}];
}

[NSOperation cancelAllOperations]; does not stop the operation

xCode 4.4.1 OSX 10.8.2, looks like [operation cancelAllOperations]; isn't working
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSOperationQueue *operation = [[NSOperationQueue alloc] init];
[operation setMaxConcurrentOperationCount: 1];
[operation addOperationWithBlock: ^{
for (unsigned i=0; i < 10000000; i++) {
printf("%i\n",i);
}
}];
sleep(1);
if ([operation operationCount] > 0) {
[operation cancelAllOperations];
}
}
results 9999999
Inside your block, particularly inside the loop, call -isCancelled on the operation. If it's true, then return.
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue setMaxConcurrentOperationCount: 1];
NSBlockOperation *operation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakOperation = operation;
[operation addExecutionBlock: ^ {
for (unsigned i=0; i < 10000000; i++) {
if ([weakOperation isCancelled]) return;
printf("%i\n",i);
}
}];
[operationQueue addOperation:operation];
sleep(1);
if ([operationQueue operationCount] > 0) {
[operationQueue cancelAllOperations];
}
A queue can't just stop the operation's execution arbitrarily - what if some shared resources were being used by the operation that never got cleaned up? It's your responsibility to orderly end the operation when it becomes known to be cancelled. From Apple's docs:
An operation object is responsible for calling isCancelled
periodically and stopping itself if the method returns YES.

Resources