iosmultithreadingafnetworkingafhttpclient

AFHTTPClient + enqueueBatchOfHTTPRequestOperations: handle cancellation and errors


My app needs to get some images from web, but I want user to be able to cancel this download (if its no connection, or it too slow, or w/e). App interface shouldn't be "frozen" in any case. So I'm using AFHTTPClient with enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock: method for downloading:

NSMutableArray *operationsArray = [NSMutableArray array];
for (NSString *imageURL in imageURLArray) {
    AFImageRequestOperation *getImageOperation =
    [AFImageRequestOperation imageRequestOperationWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageURL]]
                                         imageProcessingBlock:nil
                                                      success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
                                                          //
                                                          // Save image
                                                          //
                                                      }
                                                      failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
                                                          if((error.domain == NSURLErrorDomain) && (error.code == NSURLErrorCancelled))
                                                              NSLog(@"Image request cancelled!");
                                                          else
                                                              NSLog(@"Image request error!");
                                                      }];
    [operationsArray addObject:profileImageOperation];
}
//
// Lock user interface by pop-up dialog with process indicator and "Cancel download" button
//
[afhttpClient enqueueBatchOfHTTPRequestOperations:operationsArray
                              progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
                                  //
                                  // Handle process indicator
                                  //
                              } completionBlock:^(NSArray *operations) {
                                  //
                                  // Remove blocking dialog, do next tasks
                                  //
                              }];

If "Cancel download" button is pressed:

- (void)cancelDownloadDialogButtonClicked {
    [afhttpClient.operationQueue cancelAllOperations];
}

My problem is:

I dont know where I should check for operations errors and cancellation (I want to cancel whole download and remove UI blocking dialog in such cases). In my opinion, best place for it is in completionBlock: of enqueueBatchOfHTTPRequestOperations:, because its garantee that all operations has been done, and i got acces to NSArray *operations, so i can check is it error or cancellation, like i did in failure:. But I found that this block is not even executing in such cases (probably because of isCancelled, isFinished, isExecuting propertys mechanics).

So how should i remove UI blocking dialog and cancel download if it was an error or user pressed "Cancel download" button?

Update

Have no idea why, but in this example Cancelling batch request in AFNetworking cancellation check is in completionBlock:, exactly where I was going to put it!. But in my case this block is not executing if any operation was canceled! Maybe im missing something in configuring my AFHTTPClient?


Solution

  • To cancell all operation use

    [[client operationQueue] cancelAllOperations];
    

    To remove UI blocking dialogue

    you have to include code for removing that dialouge in

    1. where you call this code
    2. When finished succesfully in completing block

    To make it clear

    - (void)cancelDownloadDialogButtonClicked {
        [afhttpClient.operationQueue cancelAllOperations];
        //DO Remove the UI blocking mechanism here Eg.
        [SVProgressHUD dismiss];
    }