从视图控制器,作为按钮操作的结果,我需要创建一个管理一组异步远程服务调用的自定义对象,并调用触发这些服务调用的此类对象的方法。我需要视图控制器等待所有异步网络操作完成以更新其视图。由于网络操作是异步的,因此在完成所有操作后,我不知道如何从管理此任务的自定义对象通信到视图控制器。
这是我目前的代码。视图控制器中的代码片段如下所示(当前未使用result
var):
- (void)loadData
{
BOOL __block result = NO;
dispatch_queue_t queue = dispatch_queue_create(dataLoadQueue, NULL);
dispatch_async(queue,^{
Loader *loader = [[Loader alloc] init];
[loader loadData];
dispatch_async(dispatch_get_main_queue(), ^{
if (result) {
// Update view and notify success
}
else {
// Update view and notify error
}
});
});
dispatch_release(queue);
}
这是loader
自定义对象端:
- (void)loadData
{
if ([Reachability checkNetStatus]) {
Service1 *service1 = [[Service1 alloc] init];
[service1 callAsyncService];
Service2 *service2 = [[Service2 alloc] init];
[service2 callAsyncService];
// More service calls
}
else {
// Notify network not reachable
}
}
对象service1, service2... serviceN
符合NSURLConnectionDelegate
,我通过connectionDidFinishLoading:
(NSNotificationCenter
对象正在侦听此类通知,通知他们已在loader
中完成)。然后,我不知道使loader
等待所有网络操作的正确方法是什么,并通知视图控制器。
提前致谢
答案 0 :(得分:0)
如果要等到异步任务完成,可以使用信号量。看下面的例子,逻辑非常简单。我认为你很容易适应你的情况。
//create the semaphore
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[objectManager.HTTPClient deletePath:[address addressURL] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
//some code here executed in background
dispatch_semaphore_signal(semaphore); //sends a notification to release the semaphore
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//some other code here also executed in background
dispatch_semaphore_signal(semaphore); //sends a notification to release the semaphore
}];
//holds the thread until the dispatch_semaphore_signal(semaphore) is send
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
答案 1 :(得分:0)
你可能有很多方法可以做到这一点。首先,我认为在视图控制器中不需要使用GCD - 加载器已经异步执行,因此加载器的创建很快。
至于Loader如何知道其所有网络操作何时完成,你可以在一个可变数组中保存一个字符串列表,比如“1 done”,“2 done”等等,这与发送的字符串相同在connectionDidFinishLoading中调用的通知的用户信息中:所有服务都可以发送相同的通知,但具有不同的用户信息。在观察者的选择器中,删除与用户信息中的字符串相同的字符串,并检查该数组是否为空 - 如果是,则表示所有服务都已完成。此时,我将使用委托方法将数据传递回视图控制器。 Loader中有这样的东西:
- (void)viewDidLoad {
[super viewDidLoad];
self.doneStrings = [@[@"1 done", @"2 done", @"3 done", @"4 done"] mutableCopy];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationReceived:) name:@"SeriveFinishedNotification" object:nil];
}
-(void)notificationReceived:(NSNotification *) aNote {
[self.doneStrings removeObjectIdenticalTo:[aNote.userInfo objectForKey:@"doneString"]];
if (self.doneStrings.count == 0)
[delegate doSomethingWithTheData: theData];
}
您可能需要处理其他一些事情,例如处理某些网络操作失败的情况。
答案 2 :(得分:0)
您还没有分享这些异步请求如何工作的详细信息,但另一种方法是将这些异步请求NSOperation
对象提交给NSOperationQueue
。 (AFNetworking是此类实现的一个示例。)执行此操作时,您可以创建另一个NSOperation
,以便在网络请求操作完成时触发,方法是使其依赖于这些网络请求操作。因此,它仅在所有网络请求完成时运行。使用基于NSOperation
的解决方案也可以享受其他好处(例如,您可以使用setMaxConcurrentOperationCount
来享受并发性,但不能在任何给定时间运行过多的并发请求。)