【问题标题】:Checking for multiple asynchronous responses from Alamofire and Swift检查来自 Alamofire 和 Swift 的多个异步响应
【发布时间】:2015-03-21 22:58:48
【问题描述】:

我正在编写一个应用程序,它依赖于来自不同站点/服务的数据,并且涉及基于来自这些不同来源的数据执行计算以生成最终产品。

我编写了一个示例类,其中包含以下两个函数,用于从两个来源收集数据。我选择使功能不同,因为有时我们会根据来源应用不同的身份验证方法,但在此示例中,我只是将它们简化为最简单的形式。这两个函数都使用 Alamofire 来触发和处理请求。

然后我有一个初始化函数,它说如果我们成功地从两个源收集数据,然后加载另一个 nib 文件,否则等待几秒钟,如果没有返回响应,然后加载服务器错误 nib 文件。

我试图让这个例子尽可能简单。本质上。这是我想遵循的逻辑。不幸的是,这似乎在当前的实现中不起作用。

import Foundation

class GrabData{
    var data_source_1:String?
    var data_source_2:String?

    init(){    
        // get data from source 1
        get_data_1{ data_source_1 in
            println("\(data_source_1)")
        }

        // get data from source 2
        get_data_2{ data_source_1 in
            println("\(data_source_1)")
        }

        var timer = 0;
        while(timer<5){
            if((data_source_1 == nil) && (data_source_2 == nil)){
                // do nothing unless 4 seconds has elapsed
                if (timer == 4){
                    // load server error nib
                }
            }else{
                // load another nib, and start manipulating data
            }
            // sleep for 1 second
            sleep(1)
            timer = timer+1
        }    
    }

    func get_data_1(completionHandler: (String) -> ()) -> () {
        if let datasource1 = self.data_source_1{
            completionHandler(datasource1)
        }else{
            var url = "http://somewebsite.com"
            Manager.sharedInstance.request(.GET, url).responseString {
                (request, response, returnedstring, error) in
                println("getting data from source 1")
                let datasource1 = returnedstring
                self.data_source_1 = datasource1
                completionHandler(datasource1!)
            }
        }
    }

    func get_data_2(completionHandler: (String) -> ()) -> () {    
        if let datasource2 = self.data_source_2{
            completionHandler(datasource2)
        }else{
            var url = "http://anotherwebsite.com"
            Manager.sharedInstance.request(.GET, url).responseString {
                (request, response, returnedstring, error) in
                println("getting data from source 2")
                let datasource2 = returnedstring
                self.data_source_2 = datasource2
                completionHandler(datasource2!)
            }
        }
    }
}

我知道我可以将第二个闭包放在 init 函数中的第一个闭包中,但是,我认为这不是最佳实践,而且我实际上是从两个以上的来源中提取的,因此闭包将是 n 个闭包深。

任何帮助找出检查多个数据源是否给出有效响应的最佳方法以及适当处理的任何帮助将不胜感激。

【问题讨论】:

    标签: ios swift asynchronous data-synchronization alamofire


    【解决方案1】:

    比会阻塞线程的循环过程更好,您可以使用调度组来跟踪请求何时完成。因此,在发出每个请求之前“进入”组,在请求完成时“离开”组,并设置一个“通知”块/关闭,当所有组的任务完成时将调用它。

    例如,在 Swift 3 中:

    let group = DispatchGroup()
    
    group.enter()
    retrieveDataFromURL(url1, parameters: firstParameters) {
        group.leave()
    }
    
    group.enter()
    retrieveDataFromURL(url2, parameters: secondParameters) {
        group.leave()
    }
    
    group.notify(queue: .main) {
        print("both requests done")
    }
    

    或者,在 Swift 2 中:

    let group = dispatch_group_create()
    
    dispatch_group_enter(group)
    retrieveDataFromURL(url1, parameters: firstParameters) {
        dispatch_group_leave(group)
    }
    
    dispatch_group_enter(group)
    retrieveDataFromURL(url2, parameters: secondParameters) {
        dispatch_group_leave(group)
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue()) {
        print("both requests done")
    }
    

    另一种方法是将这些请求包装在异步 NSOperation 子类中(使它们可取消,让您控制限制并发程度等),但这更复杂,因此您可能希望从调度开始组如上所示。

    【讨论】:

    猜你喜欢
    • 2018-09-10
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 2019-07-18
    • 2014-11-24
    • 2018-10-14
    • 1970-01-01
    相关资源
    最近更新 更多