Ios 如何处理3个不同但同时进行的异步调用

Ios 如何处理3个不同但同时进行的异步调用,ios,objective-c,multithreading,objective-c-blocks,mutability,Ios,Objective C,Multithreading,Objective C Blocks,Mutability,这是我关心的问题:出于某种原因,我必须检索并分组来自3个不同web请求结果的答案。一旦其中3个返回,我必须调用completionBlock并将所有结果传递给它。 使用NSOperation API,我成功地做到了以下几点: Session * session = [[ServiceLocator sharedInstance] serviceForName:ServiceLocatorNameUserRepository]; NSString * urlMethod = @"POST";

这是我关心的问题:出于某种原因,我必须检索并分组来自3个不同web请求结果的答案。一旦其中3个返回,我必须调用completionBlock并将所有结果传递给它。 使用NSOperation API,我成功地做到了以下几点:

Session * session = [[ServiceLocator sharedInstance] serviceForName:ServiceLocatorNameUserRepository];


NSString * urlMethod = @"POST";
NSDictionary * params = @{kParkadomWebServiceUser : session.currentUser.userID};

NSMutableDictionary * records = [NSMutableDictionary new];

NSOperation * currentBooking = [self performRequestWithPath:API_BOOKING_INPROGRESS
                                                         method:urlMethod
                                                      parameter:params
                                                     completion:^(id json, NSError * error)
                                                     {
                                                         records[@"current"] = error ? error : json;

                                                     }];

NSOperation * upcomingBookings = [self performRequestWithPath:API_BOOKING_UPCOMING
                                                         method:urlMethod
                                                      parameter:params
                                                     completion:^(id json, NSError * error)
                                                     {
                                                         records[@"upcoming"] = error ? error : json;

                                                     }];

NSOperation * pastBookings = [self performRequestWithPath:API_BOOKING_HISTORY
                                                   method:urlMethod
                                                parameter:params
                                               completion:^(id json, NSError * error)
                                               {
                                                   records[@"past"] = error ? error : json;

                                               }];


NSBlockOperation * completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    completion([records copy], nil);
}];
[completionOperation addDependency:currentBooking];
[completionOperation addDependency:upcomingBookings];
[completionOperation addDependency:pastBookings];

[[NSOperationQueue mainQueue] addOperation:completionOperation];
其中completion显然是作为入口参数给出的completion块。 performRequestWithPath:method:parameter:completion:创建一个NSOperation,将其添加到全局队列并返回,因此我在这里有3个web调用。然后,我创建一个块操作,并将依赖项添加到前3个块中,以便在3个块完成之前不会触发依赖项

我关心的是NSMutableArray的事情。这样做似乎是一个糟糕的设计,我不确定它是否真的能在案例2的调用同时完成的情况下防止bug。(注意,我在perform…:方法中确保在主队列中调用完成块)

有什么反馈吗?建议、批评、理论。。。我完全打开了:)

如果您的“记录”字典用于在这些异步调用中添加键/值的单一目的,那么您可以通过在添加三个值的代码周围放置@synchronized(records){…}来轻松地做到这一点


如果完成块在主队列上执行,则它们不能同时执行。但是,您必须仔细检查代码:这三个操作可能在完成块完成之前完成

您需要添加同步

@synchronized(myArray) {
  [myArray doSomething];
}
例如,在代码中:

@synchronized(records) {
    records[@"past"] = error ? error : json;
}

编辑:@gnasher729提出了一个很好的观点,即如果完成块在主线程上运行,那么就不需要同步。

我确保完成块在主线程中执行,但是,无论如何,我将使用@synchronized,更安全,这感觉好多了:)我以为AddDependence会阻止在完成3个块之前调用completionBlock?一个同步块是不够的。您还需要确保您在NSDictionary中接触的值也可以原子访问。无论如何,不需要添加线程保护。请看下面我的答案。@FlorianBurel:只有当三个NSO操作全部完成时,最终的completionBlock才会开始。但是,如果这些NSO操作使用dispatch_async在主线程上执行它们的完成块,那么NSO操作将在dispatch_async之后完成,在完成块开始运行之前很长一段时间
@synchronized(myArray) {
  [myArray doSomething];
}