等到多个网络请求都已执行 - 包括完成块

cho*_*ise 39 cocoa-touch asynchronous objective-c httprequest ios

我有多个操作(它们是AFNetworking请求),其中包含需要一些时间才能执行的完成块,以及需要在所有请求结束时保存的Core Data对象.

MyCoreDataObject *coreDataObject;

AFHTTPRequestOperation *operation1 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation1 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    coreDataObject.attribute1 = responseObject;
    sleep(5);
}];
[operation1 start];

AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    coreDataObject.attribute2 = responseObject;
    sleep(10);
}];
[operation1 operation2];

[context save:nil];
Run Code Online (Sandbox Code Playgroud)

当然,这不是我想要的,因为请求是异步的.我尝试添加NSOperationQueue,如下所示:

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue setMaxConcurrentOperationCount:2];

AFHTTPRequestOperation *operation1 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation1 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    coreDataObject.attribute1 = responseObject;
    sleep(5);
}];
[operationQueue addOperation:operation1];

AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    coreDataObject.attribute2 = responseObject;
    sleep(10);
}];
[operationQueue addOperation:operation2];

[imageQueue waitUntilAllOperationsAreFinished];
[context save:nil];
Run Code Online (Sandbox Code Playgroud)

这看起来好一点.使用waitUntilAllOperationsAreFinished,我的队列阻止当前线程,直到我的请求完成,但直到我的成功块完成,这才是我真正需要的.

关于如何以良好的方式实现这一目标的任何想法?

Ken*_*ses 84

使用调度组.

dispatch_group_t group = dispatch_group_create();

MyCoreDataObject *coreDataObject;

dispatch_group_enter(group);
AFHTTPRequestOperation *operation1 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation1 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    coreDataObject.attribute1 = responseObject;
    sleep(5);
    dispatch_group_leave(group);
}];
[operation1 start];

dispatch_group_enter(group);
AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    coreDataObject.attribute2 = responseObject;
    sleep(10);
    dispatch_group_leave(group);
}];
[operation2 start];

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);

[context save:nil];
Run Code Online (Sandbox Code Playgroud)

  • 嗯,如果没有阻止线程,"**等待**直到执行多个操作"是什么意思?无论如何,如果你只想在所有完成块运行后运行一个块,你可以使用`dispatch_group_notify(group,queue,^ {...});`而不是`dispatch_group_wait()`. (22认同)

小智 15

AFNetworking设计了这种操作的方法,从GCD中抽象出来:

-enqueueBatchOfHTTPRequestOperationsWithRequests:progressBlock:completionBlock:

-enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:

看看FAQ