1

这是我的担忧:出于某种原因,我必须从 3 个不同的 Web 请求结果中检索和分组答案。一旦他们三个返回,我必须调用一个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 显然是作为入口参数给出的完成块。performRequestWithPath:method:parameter:completion: 创建一个 NSOperation,将它添加到全局队列并返回它,所以我在这里有 3 个网络调用。然后我创建一个块操作并将依赖项添加到前 3 个块中,因此在 3 个块完成之前不会触发它。

我担心的是 NSMutableArray 的事情。做这样的事情似乎是一个糟糕的设计,我不确定如果 2 个调用同时完成,它是否真的是 bug 证明。(请注意,我在 perform...: 方法中确保在主队列中调用完成块)。

任何反馈?建议,批评,理论......我很开放:)

4

2 回答 2

2

如果您的“记录”字典仅用于在这些异步调用中添加键/值,您可以通过在添加三个值的代码周围放置 @synchronized (records) { ... } 轻松完成此操作。

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

于 2014-12-12T13:57:44.360 回答
1

您将需要添加同步。

@synchronized(myArray) {
  [myArray doSomething];
}

例如,在您的代码中:

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

编辑:@gnasher729 提出了一个好处,即如果完成块在主线程上运行,则不需要同步。

于 2014-12-12T13:58:14.020 回答