guidev
guidev

Reputation: 2865

Wait for multiple AFNetworking requests to complete

I need to wait for several AFNetworking requests to complete, i tried using dispatch groups, but I can't seem to get it right.

Here's my code:

dispatch_group_t group = dispatch_group_create();

for (int k = 0; k < 10 ; k++) {
    dispatch_group_enter(group);

    [[AFHTTPSessionManager manager] GET:@"http://google.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"success");
        dispatch_group_leave(group);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"failure");
        dispatch_group_leave(group);
    }];
}

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"DONE");

The problem is that it gets stuck on dispatch_group_wait, because neither the success block, nor the failure blocks are called.

How can I solve it?

Upvotes: 6

Views: 2508

Answers (4)

Monideep
Monideep

Reputation: 2810

You can use this helper function to block the main thread.

static inline void hxRunInMainLoop(void(^block)(BOOL *done)) {
__block BOOL done = NO;
block(&done);
while (!done) {
    [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow:.1]];
}
}

Yo also need to implement a counter and increment it on success or failure.

- (void)test {
  __block int count = 0;

  hxRunInMainLoop(^(BOOL *done) {

    for (int i = 0; i < 10; i++) {

    [AFHTTPSessionManager manager] GET:@"http://google.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
      NSLog(@"success");
      count++;
      if (count == 9) {
        *done = YES;
      }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
      NSLog(@"failure");
      count++;
      if (count == 9) {
        *done = YES;
      }
    }];
}

This will block the main thread until done is set to YES.

Upvotes: 0

酷酷的哀殿
酷酷的哀殿

Reputation: 1031

The dispatch queue for completionBlock. If NULL (default), the main queue is used.

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t queue = dispatch_queue_create("com.app", DISPATCH_QUEUE_CONCURRENT);

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.completionQueue = queue;
for(int k = 0; k < 10; k++) {
    dispatch_group_enter(group);

    dispatch_async(queue, ^{
        NSLog(@"%d", k);
        [manager GET:@"http://baidu.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
             NSLog(@"success");
             dispatch_group_leave(group);
         } failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
             NSLog(@"failure");
             dispatch_group_leave(group);
         }];
    });
}

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"DONE");

Upvotes: 10

Mohshin Shah
Mohshin Shah

Reputation: 298

You can use PromiseKit .Very powerful.

Sequential

      [self.manager GET:@"http://www.error-url.ss/" parameters:nil].then(^(id responseObject, AFHTTPRequestOperation *operation){
        NSLog(@"first request completed for operation: %@", operation.request.description);
        return [self.manager GET:@"http://www.apple.com" parameters:nil];
    }).then(^{
        NSLog(@"second request completed");
    }).catch(^(NSError *error){
        NSLog(@"error happened: %@", error.localizedDescription);
        NSLog(@"original operation: %@", error.userInfo[AFHTTPRequestOperationErrorKey]);
    });

OR (as per your requirement)

        [PMKPromise when:@[
                       [self.operationManager GET:@"ip" parameters:nil].then(^(){numberOfOperationsCompleted ++;}),
                       [self.operationManager GET:@"get" parameters:nil].then(^(){numberOfOperationsCompleted ++;})
                       ]].then(^(){
        //do something when all operations are finished
    });

Upvotes: 0

Ketan Parmar
Ketan Parmar

Reputation: 27428

Try this,

  dispatch_group_t group = dispatch_group_create();

for (int k = 0; k < 10 ; k++) {
    dispatch_group_enter(group);

    [[AFHTTPSessionManager manager] GET:@"http://google.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"success");
        dispatch_group_leave(group);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"failure");
        dispatch_group_leave(group);
    }];
}

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

    NSLog(@"All done");

});

dispatch_group_notify will get called when all task will be completed.

Upvotes: 0

Related Questions