2016-04-24 36 views
5

Devo aspettare che vengano completate diverse richieste di AFNetworking, ho provato a utilizzare i gruppi di dispatch, ma non riesco a farlo correttamente.Attendi il completamento di più richieste AFNetworking

Ecco il mio codice:

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"); 

Il problema è che si blocca sul dispatch_group_wait, perché né il blocco di successo, nè i blocchi di guasto sono chiamati.

Come posso risolverlo?

+0

Hai provato a utilizzare dispatch_group_notify? – jtbandes

+0

sì, funziona. Tuttavia ciò non risolve il mio problema. A causa di come è stata costruita l'app (ho ereditato il progetto), ho bisogno di interrompere l'esecuzione del metodo. – guidev

+0

Questo è sfortunato; potresti prendere in considerazione la possibilità di refactoring. Se blocchi il thread, perderai una discussione il cui unico compito è aspettare che un altro thread faccia qualcosa. libdispatch impone un limite di 64 thread che verrà avviato per la manutenzione delle code, quindi a seconda di ciò che sta facendo l'applicazione può diventare un problema. – jtbandes

risposta

6

La coda di invio per completionBlock. Se NULL (predefinito), viene utilizzata la coda principale.

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"); 
0

Prova questo,

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 verrà chiamato quando tutto operazione sarà completata.

0

È possibile utilizzare PromiseKit. Molto potente.

sequenziale

 [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]); 
    }); 

O (secondo il vostro requisito)

 [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 
    }); 
0

È possibile utilizzare questa funzione di supporto per bloccare la filettatura principale.

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

Inoltre, è necessario implementare un contatore e incrementarlo in caso di esito positivo o negativo.

- (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; 
     } 
    }]; 
} 

Questo bloccherà il thread principale finché non è impostato su SÌ.