1

I've got subclass of AFHTTPClient The main idea is that i call all API through my singleton of AFHTTPClient subclass, and all requests goes through 1 points for error handling and HUD displaying. This is entry point for every API calls:

-(void) makeRequestWithPath:(NSString*) path andParams:(NSDictionary*) params 
                    success:(void (^)( id JSON, AFHTTPRequestOperation *operation)) success
                    failure:(void (^)( NSError *error)) failure

And i've got many methods for API calls something like that:

-(void) getListMainTreeWithSuccess:(void (^)( id JSON, AFHTTPRequestOperation *operation)) success
                       failure:(void (^)( NSError *error)) failure
{

[self makeRequestWithPath:@"objects/selectlist" andParams:nil success:^(id JSON, AFHTTPRequestOperation *operation) {
    success(JSON,operation);
} failure:^(NSError *error) {
    failure(error);
}];

}

This works just fine for my needs. But i faced problem that i need to make serial request in loop through my AFHTTPClient subclass and make some action when all of them are finished , I found method

-(void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)urlRequests
                                      progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock
                                    completionBlock:(void (^)(NSArray *operations))completionBlock

which should solve my issue, but the problem is that i call all methods through AFHTTPClient and it's methods getPath: and postPath: and previous way forces me to rewrite everything and makes my subclass completely useless, because I need to add there NSArray of AFHTTPRequestoperation, which is not possible to construct or extract from my subclass and my methods. Previously i tried to use __block 's to synchronise requests with semaphore and something else but i failed to get what i need, please help me!

UPDATE: It seems that it is not possible to even use enqueueBatchOfHTTPRequestOperations method (even with rewriting all my code) because this method needs array of http request operations, but it's not possible to construct POST request with them.

Julian
  • 9,299
  • 5
  • 48
  • 65
KysokZla
  • 25
  • 5

2 Answers2

0

I solved this with an increment/decrement pending download system and tied the HUD to that.

[networkStatus beginNetworkActivity];
[client someRESTActionWithCompletion:^(id object, NSError *error) {
    [networkStatus endNetworkActivity];

    if (error) {
        // Handle the error ...
    }

    if (![networkStatus hasNetworkActivity]) {
        // All downloads have finished
    }
}];

I keep the network status object separate which from the AFHTTPClient subclass, but it can be built into the client if that's what you want.

Network status keeps an internal counter. -beginNetworkActivity increments the counter, if the counter was 0, then it displays a HUD. -endNetworkActivity decrements the counter, if the counter becomes 0, then it dismisses the HUD. -hasNetworkActivity returns YES if the counter greater than 0.

Other Notes: I combine the success and failed callbacks into a single completion callback. I keep the network status logic separate from the client because sometime I'll use a singleton network status object, sometimes I'll use a created instance, sometimes I won't use one at all. It all depends on the needs to the higher level logic.

Community
  • 1
  • 1
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
  • Thanks for the answer, but i don't have problem displaying HUD, i've already realised it in my subclass of AFHTTPClient. I've got a problem executing many request through AFHTTPClient in one place and so that i know when exactly ALL of them are finished so i can execute further code. With ASIHTTP it was easy because all the answers were going to one single method, and all of the request was executing one after another, so i exactly knew when all of them are finished. – KysokZla Jan 14 '14 at 11:38
  • @KysokZla `[networkStatus hasNetworkActivity]` would return NO when all requests have finished. It is the indicator you are looking for. – Jeffery Thomas Jan 15 '14 at 13:04
0

Again, as @MikePollard said, create AFHTTPRequestOperation using

[AFHHTPClient HTTPRequestOperationWithRequest:success:failure:]

For this method create NSURLRequest using (or use another one, pick which one is suitable for you). Here you can also specify, which method to use POST, GET or any other.

[AFHTTPClient requestWithMethod:
                           path:
                     parameters:]

After that save all operation to an NSArray, and schedule them using:

[AFHTTPClient enqueueBatchOfHTTPRequestOperationsWithRequests:
                                                progressBlock:
                                              completionBlock:]

Code example:

NSMutableArray *ops = [NSMutableArray new];
NSMutableURLRequest *request1 = [[AFHTTPClient sharedClient] requestWithMethod:@"GET"
                                                                          path:@"MyEndpoint"
                                                                    parameters:@{@"key1": @"value"}];
AFHTTPRequestOperation *op1 = [[AFHTTPClient sharedClient] HTTPRequestOperationWithRequest:request1
                                                                                   success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                                                       NSLog(@"Success!");
                                                                                   }
                                                                                   failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                                                       NSLog(@"Failure!");
                                                                                   }];
[ops addObject:op1];

NSMutableURLRequest *request2 = [[AFHTTPClient sharedClient] requestWithMethod:@"POST"
                                                                          path:@"MyAnotherEndpoint"
                                                                    parameters:@{@"key2": @(104)}];
AFHTTPRequestOperation *op2 = [[AFHTTPClient sharedClient] HTTPRequestOperationWithRequest:request2
                                                                                   success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                                                       NSLog(@"Success!");
                                                                                   }
                                                                                   failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                                                       NSLog(@"Failure!");
                                                                                   }];
[ops addObject:op2];
[[AFHTTPClient sharedClient] enqueueBatchOfHTTPRequestOperationsWithRequests:ops
                                                               progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
                                                                   NSLog(@"numberOfFinishedOperations: %d totalNumberOfOperations %d",
                                                                         numberOfFinishedOperations,
                                                                         totalNumberOfOperations);
                                                               }
                                                             completionBlock:^(NSArray *operations) {
                                                                 NSLog(@"All operation compelted!");
                                                             }];
Vytautas
  • 573
  • 3
  • 8
  • Sorry, i can't understand your answer( Could u provide a simple code, with, for example, 2 different POST request with 2 different params for each and executing them with ur approach. Would appreciate your help very much – KysokZla Jan 14 '14 at 11:28
  • Exactly i'm not getting how is it possible to save HTTPRequestOperation object through [AFHHTPClient HTTPRequestOperationWithRequest:success:failure:] because this object is only available in success block, and this block only comes up when operation is finished. Am i wrong somewhere? – KysokZla Jan 14 '14 at 11:44
  • Yes, you're missing something there, it is always good practice to take a look to documentation or header file. But anyway, I have added an example, I hope now you will understand the idea. – Vytautas Jan 14 '14 at 13:02
  • Good to know, there is a mistake in your example: `enqueueBatchOfHTTPRequestOperationsWithRequests` takes an array of NSURLRequest. `enqueueBatchOfHTTPRequestOperations` actually takes an array of AFHTTPRequestOperation. You're mixing the both in your code, it's not gonna work. – Ben Jul 02 '15 at 11:39