0

从视图控制器中,作为按钮操作的结果,我需要创建一个自定义对象来管理一组异步远程服务调用,并调用触发这些服务调用的此类对象的方法。我需要视图控制器等待所有异步网络操作完成才能更新其视图。由于网络操作是异步的,我不知道在所有操作完成后如何从管理此任务的自定义对象到视图控制器进行通信。

这是我目前拥有的代码。视图控制器中的代码片段是这样的(resultvar 当前未使用):

- (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:NSNotificationCenterloaderloader等待所有网络操作并通知视图控制器的正确方法是什么。

提前致谢

4

3 回答 3

0

您还没有分享这些异步请求如何工作的详细信息,但另一种方法是将这些异步请求NSOperation对象提交给NSOperationQueue. (AFNetworking 是这种实现的一个示例。)当您这样做时,您可以创建另一个NSOperation在网络请求操作完成时触发,方法是使其依赖于这些网络请求操作。因此,它只会在所有网络请求都完成后运行。使用NSOperation基于 - 的解决方案还有其他好处(例如,您可以使用setMaxConcurrentOperationCount它让您享受并发,但在任何给定时间都不会运行太多并发请求)。

参考

于 2013-08-01T05:19:56.667 回答
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]];
}
于 2013-08-01T04:12:48.040 回答
0

可能有很多方法可以做到这一点。首先,我认为没有必要在视图控制器中使用 GCD —— loader 已经在异步执行操作,所以 loader 的创建速度很快。

至于 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];
}

您可能需要处理一些其他事情,例如处理某些网络操作失败的情况。

于 2013-08-01T05:01:40.140 回答