以下是我的担忧:出于某种原因,我必须检索并分组来自3个不同网络请求结果的答案。一旦其中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];
其中,完成显然是作为入口参数给出的完成块。 performRequestWithPath:方法:参数:完成:创建一个NSOperation,将其添加到全局队列并返回它,所以我在这里进行了3次Web调用。然后我创建一个块操作并将依赖项添加到前一个3块,以便在3个块完成之前不会触发它。
我关心的是NSMutableArray的东西。做这样的事情似乎是一个糟糕的设计,我不确定它是否真的可以在案例2调用完全同时完成时进行错误验证。 (注意我在perform ...中确定了在主队列中调用完成块的方法。)
有任何反馈意见吗?建议,批评,理论......我全都开放了:)
答案 0 :(得分:2)
如果您的“记录”字典用于在这些异步调用中添加键/值的单一目的,您可以通过在添加三个的代码周围放置@synchronized(records){...}来轻松完成此操作值。
如果完成块在主队列上执行,则它们不能同时执行。但是,您必须仔细检查您的代码:三个操作可能在完成块完成之前完成!
答案 1 :(得分:1)
您需要添加同步。
@synchronized(myArray) {
[myArray doSomething];
}
例如,在您的代码中:
@synchronized(records) {
records[@"past"] = error ? error : json;
}
编辑:@ gnasher729提出了一个好处,即如果它们在主线程上运行完成块,那么就不需要同步。