12
votes

I use this AFNetworking method to start multiple requests at once:

- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations 
                              progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock 
                            completionBlock:(void (^)(NSArray *operations))completionBlock

One of them is a AFJSONRequestOperation. The problem is that the success-block of this JSON operation is executed after the completion-block of the batch. The reason is: AFJSONRequestOperation has an internal dispatch queue for JSON processing. So the JSON data is still in processing while the completion block is called.

Question: How can execute code in the completion block after the success block of the JSON operation has been called?

I tried to dispatch a code block on the main queue but that didn't help.

3

3 Answers

1
votes

If it's possible, the simplest solution might be just to move your processing code from the success block of each operation to the completion block of the whole batch.

You have the NSArray *operations available in the completion block, you can iterate through the operations and look for:

for(AFHTTPRequestOperation *operation in operations){
   if(operation.response.statusCode == 200){
      //Do something with the response
   }else{
     //Handle the failure
   }
}

You also have the url address for each operation available through the operation.request.URL property if you need to preform different actions

0
votes

You can move your Json operation to the beginning of the queue, and then add a dependency so that another operation can only start after the json operation finishes:

    [lastOperation addDependency:jsonOperation]
0
votes

It appears there is no easy way to do exactly what the OP requests, so here are some easy workarounds.

A rather blunt strategy would be to use AFHTTPRequestOperation instead of AFJSONRequestOperation and then convert the response using NSJSONSerialization.

So the success block of the operation would look like

  success:^(AFHTTPRequestOperation *operation, id responseObject){
              NSError *error ;
              id json = [NSJSONSerialization JSONObjectWithData:responseObject 
                                            options:kNilOptions error:&error] ;
              ... 
            }

Caveats would apply - for large JSON responses this is potentially blocking code, and some of the AFNetworking workarounds to NSJSONSerialization issues would not apply. But this would get you going.

Update: The first commenter below suggests using AFJSONRequestOperation and calling responseJSON on it in the batch completion block. I'm good with that if your situation allows it. In my current use case it complicates my code somewhat (I'm using a mixed set of JSON calls, so the code is cleaner if I can keep it in a success block directly associated with the operation).