【问题标题】:How to synchronize two asynchronous delegate methods callbacks in iOS?如何在 iOS 中同步两个异步委托方法回调?
【发布时间】:2015-07-25 02:44:03
【问题描述】:

我正在编写一个简单的天气应用程序来巩固我对协议和委托的理解。我的情况如下:

  • 我有 2 个用于天气数据的数据源(此时只有 NSObjects)和一个视图控制器,一旦我收到来自两个源的数据,我想更新它。
  • 这两个数据源具有我在视图控制器中遵守的协议。一旦他们从自己的 Web 服务接收到数据,就会调用他们的委托方法。这可能意味着数据源 1 在数据源 2 之前获取数据,反之亦然,或者同时获取数据(如果可能,不知道 100%)
  • 我只想在收到来自两个来源的数据后更新视图。

最好的方法是什么?我正在考虑嵌套委托方法,其中数据源 1 在有数据时会通知数据源 2(通过协议),然后让数据源 2 在有数据时通知视图控制器更新视图。但是,我认为这不是正确/最佳的做事方式。

有什么想法吗?

谢谢

【问题讨论】:

  • 只是出于好奇,您如何看待Data Source 1 失败而Data Source 成功的情况?在这种情况下,数据源 1 是否知道如何重试?

标签: ios objective-c protocols


【解决方案1】:

这听起来很适合 GCD 调度组。

首先,使用dispatch_group_create 创建一个调度组。然后在开始请求每个服务之前使用dispatch_group_enter。当您收到来自每个服务的响应时,请致电 dispatch_group_leave。您可以使用dispatch_group_notify 指定两个请求都完成时要执行的操作。

代码可能如下所示:

dispatch_group_t weatherGroup = dispatch_group_create();

dispatch_group_enter(weatherGroup);
[weatherService1 requestWithCompletion:^(Response *response){
    // Do something with the response
    dispatch_group_leave(weatherGroup);
}];

dispatch_group_enter(weatherGroup);
[weatherService2 requestWithCompletion:^(Response *response){
    // Do something with the response
    dispatch_group_leave(weatherGroup);
}];

dispatch_group_notify(weatherGroup, dispatch_get_main_queue(),^{
    // This is executed after both requests are finished
});

有关详细信息,请参阅文档:https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/#//apple_ref/doc/uid/TP40008079-CH2-SW19

【讨论】:

  • 这就是我要说的。您还可以根据自己的需要和喜好使用信号/信号量。
【解决方案2】:

您可以使用两个 BOOL 变量 recievedDataFromServiceOnerecievedDataFromServiceTwo。现在,一旦您的服务返回响应并保持和 AND 操作以在刷新视图之前进行检查,请立即设置它们。在 UI 刷新后都重置为 NO

if(recievedDataFromServiceOne && recievedDataFromServiceTwo) {
   //Refesh the UI
}

【讨论】:

    【解决方案3】:

    使用您在委托方法中递增的计数器属性。所以从 0 开始计数器,每个委托方法都会将它增加 1。然后您可以在属性的覆盖设置器中观察此计数器的值(我称之为计数器)

    -(void)setCounter:(NSInteger)counter {
        _counter = counter;
        if (_counter == 2) {
            NSLog(@"Both delegates have been called");
            // do your update here
        }
    } 
    

    【讨论】:

    • “然后您可以在属性的覆盖设置器中观察此计数器的值(我称之为计数器)” - 我对您的意思有点困惑?这与每次增加计数器后检查计数器(查看它是否为 2)相同吗?
    • @p0ny,每次设置 counter 的值时都会调用 setter (setCounter:) (这就是 setter 的作用),所以你不需要“检查”,它会当你增加时调用。您需要确保在执行递增时使用属性语法 -- self.counter +=1;
    猜你喜欢
    • 2010-11-27
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多