当您调用 AFNetworking GET 方法时,它会返回一个 AFHTTPRequestOperation(一个 NSOperation 子类)。您可以利用这一事实为您的问题采用基于操作队列的解决方案。也就是说,您可以创建一个新的“完成操作”,它依赖于特定 AFNetworking 操作的完成。
例如,您可以更改getEachItem 方法以返回GET 方法返回的AFHTTPRequestOperation。例如,假设您有一个getEachItem,当前定义如下:
- (void)getEachItem:(id)identifier
{
// do a lot of stuff
[self.manager GET:... parameters:... success:... failure:...];
}
将其更改为:
- (NSOperation *)getEachItem:(id)identifier
{
// do a lot of stuff
return [self.manager GET:... parameters:... success:... failure:...];
}
然后,您可以创建自己的完成操作,该操作将依赖于所有其他 AFHTTPRequestOperation 操作的完成。因此:
NSOperation *completion = [NSBlockOperation blockOperationWithBlock:^{
[self showNavigation];
}];
NSArray *tmpItems=[result objectForKey:@"ipad_items"];
for(NSDictionary *m in tmpItems){
// will also increment into the _menus array
NSOperation *operation = [self getEachItem:[m objectForKey:@"id"]];
[completion addDependency:operation];
[self getImages:[m objectForKey:@"id"]];
}
[[NSOperationQueue mainQueue] addOperation:completion];
完成此操作后,在所有 getEachItem 操作完成之前,completion 操作将不会触发。请注意,此完成操作将在核心 AFHTTPRequestOperation 对象完成时触发,但不能保证这些请求的相应完成块一定完成。
另一种方法是使用 GCD“组”。使用这种技术,您在提交每个请求时“进入”组,然后在 GET 方法的完成块中“离开”组。然后,您可以指定当该组通知您离开该组的次数与您进入该组的次数一样多时要执行的代码块(即所有 AFNetworking 网络请求及其success/failure块,完成)。
例如,给getEachItem添加一个dispatch_group_t参数:
- (void)getEachItem:(id)identifier group:(dispatch_group_t)group
{
dispatch_group_enter(group);
// do a lot of stuff
[self.manager GET:... parameters:... success:^(...) {
// do you success stuff and when done, leave the group
dispatch_group_leave(group);
} failure:^(...) {
// do you failure stuff and when done, leave the group
dispatch_group_leave(group);
}];
}
注意,您在提交请求之前“进入”组,两个success 和failure 块必须调用dispatch_group_leave。
完成此操作后,您现在可以在请求循环中使用 dispatch_group_t,当组收到所有已完成的通知时执行 showNavigation:
dispatch_group_t group = dispatch_group_create();
NSArray *tmpItems=[result objectForKey:@"ipad_items"];
for(NSDictionary *m in tmpItems){
// will also increment into the _menus array
[self getEachItem:[m objectForKey:@"id"] group:group];
[self getImages:[m objectForKey:@"id"]];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self showNavigation];
});