当前位置 : 主页 > 手机开发 > 其它 >

swift – 使用Alamofire对不同的API进行多次调用 – 如何将结果保存到数组中?

来源:互联网 收集:自由互联 发布时间:2021-06-11
我正在开发一个应用程序,它使用Alamofire从几个不同的API中获取数据(每个调用都是使用函数完成的).然后我必须收集所有结果(在我的情况下为Double类型)到一个数组来计算平均值. 只要A
我正在开发一个应用程序,它使用Alamofire从几个不同的API中获取数据(每个调用都是使用函数完成的).然后我必须收集所有结果(在我的情况下为Double类型)到一个数组来计算平均值.

只要Alamofire使用异步调用,就不可能简单地从调用内部向数组添加新值.

这是一个函数,它调用负责通过Alamofire获取数据的每个函数:

func collectData() {
   fetchFromFirstAPI()
   fetchFromSecondAPI()  //etc.
}

以下是其中一个功能的示例:

func fetchFromFirstAPI() {
   let APIKey = "XXXXXXXXX"
   let APIURL = "http://urlapi.com/api" as URLConvertible

   let parameters: Parameters = ["APPKEY": APIKey]

   Alamofire.request(APIURL, method: .get, parameters: parameters, encoding: URLEncoding.default).validate().responseJSON { response in
        switch response.result {
        case .success(let data):
            let json = JSON(data)
            if let result = json["main"]["value"].double {
                myArray.append(result)
            } else {
                print("error")
            }
        case .failure:
            print("error")
        }
   }
}

而阵列:

var myArray: [Double] = []

怎么处理呢?

你说:

As long as Alamofire uses asynchronous calls, it is impossible to simply append new value to an array from inside of call.

您实际上可以继续将项目附加到完成处理程序内的数组中.并且由于Alamofire默认在主队列上调用其完成处理程序,因此无需进一步同步.您可以使用调度组来了解所有请求何时完成.首先,我会给我的方法完成处理程序,所以我知道它们什么时候完成,例如:

func fetchFromFirstAPI(completionHandler: @escaping (Double?, Error?) -> Void) {
    let APIKey = "XXXXXXXXX"
    let APIURL = "http://urlapi.com/api"

    let parameters: Parameters = ["APPKEY": APIKey]

    Alamofire.request(APIURL, parameters: parameters).validate().responseJSON { response in
        switch response.result {
        case .success(let data):
            let json = JSON(data)
            if let result = json["main"]["value"].double {
                completionHandler(result, nil)
            } else {
                completionHandler(nil, FetchError.valueNotFound)
            }
        case .failure(let error):
            completionHandler(nil, error)
        }
    }
}

哪里

enum FetchError: Error {
    case valueNotFound
}

然后你可以做类似的事情:

func performRequestsAndAverageResults(completionHandler: @escaping (Double?) -> ()) {
    var values = [Double]()
    let group = DispatchGroup()

    group.enter()
    fetchFromFirstAPI { value, error in
        defer { group.leave() }
        if let value = value { values.append(value) }
    }

    group.enter()
    fetchFromSecondAPI { value, error in
        defer { group.leave() }
        if let value = value { values.append(value) }
    }

    group.notify(queue: .main) {
        completionHandler(self.average(values))
    }
}

func average<T: FloatingPoint>(_ values: [T]) -> T? {
    guard values.count > 0 else { return nil }

    let sum = values.reduce(0) { $0 + $1 }
    return sum / T(values.count)
}

现在,您可能希望以不同方式处理错误,但这应该说明基本思路:只需将结果附加到完成处理程序中,然后使用调度组知道所有请求何时完成,并在通知闭包中执行任何计算想.

显然,上面的代码并不关心这些异步任务的完成顺序.如果您确实关心,则需要稍微调整一下(例如将结果保存到字典中,然后构建排序数组).但是如果你只是对结果求平均值,那么顺序并不重要,而且上面的内容相当简单.

网友评论