Работа с обработчиками завершения Swift для связанных функций - PullRequest
0 голосов
/ 02 июля 2018

Я соединяю некоторые функции вместе и не могу понять, как вызвать обработчик завершения с возвращаемым значением, как только все функции будут выполнены.

class AirQualityProvider {
    var aBlock: ((Int?) -> Void)?

    func getAirQuality(completion: @escaping (Int?) -> Void) {
        aBlock = completion
        callAPI()
    }

    private func callAPI() {
        let data = Data()
        parseDataForAQI(data: data)
    }

    private func parseDataForAQI(data: Data) {

        for d in data {
            dosomeMath(d)
        }
    }


    private func dosomeMath(data: Int) {

        // HERE IS WHERE I WANT IT TO SUM UP ALL THE NUMBERS
        THEN ONLY RETURN ONE VALUE using a completion handler.
        Currently, it returns the average as it is being generated.
    }

Почти все заработало с помощью Александра. Код, предоставленный Александром, работает отлично, это потрясающе. Проблема в том, что когда я запускаю Taskrunner внутри alamofire, он возвращается пустым. Снаружи alamofire все работает как обычно. Мне нужно запустить это внутри alamofire.

func A(json : JSON){
    for (key,subJson) in json{
        if subJson["free"].doubleValue > 0.0 {
            func B(asset: subJson["asset"].stringValue, json: subJson)
        }
    }

    print(taskRunner.getResults())
}


func B(asset : String, json : JSON){

        //OUTSIDE ALAMOFIRE WORKS
            self.taskRunner.execute{
            return 100
        }

    Alamofire.request(url).responseJSON { response in

       //INSIDE ALAMOFIRE DOESN'T WORK. Returns []
            self.taskRunner.execute{
            return 100
        }

    }

}

1 Ответ

0 голосов
/ 03 июля 2018

Я бы использовал очередь отправки для синхронизации агрегации результатов (путем синхронизации вызовов Array.append(_:) и последующего чтения массива). Вот простой пример:

import Dispatch
import Foundation

class ParallelTaskRunner<Result> {
    private var results = [Result]()
    private let group = DispatchGroup()
    private let resultAggregatorQueue = DispatchQueue(label: "Result Aggregator")

    func execute(_ closure: (@escaping (Result) -> Void) -> Void) {
        group.enter() // Register that a new task is in-flight
        closure { result in
            self.resultAggregatorQueue.sync { // Synchronize access to the array
                self.results.append(result) // Record the result
            }
            self.group.leave() // This task is done
        }
    }

    func getResults() -> [Result] {
        group.wait() // Make sure all in-flight tasks are done
        return resultAggregatorQueue.sync { return results }
    }
}




let taskQueue = DispatchQueue(label: "Task Queue", attributes: .concurrent)
let taskRunner = ParallelTaskRunner<Int>()
for i in 0...100 {
    taskRunner.execute { completionHandler in 
        taskQueue.async { // Simulated async computation
            let randomTime = 3.0
            print("Sleeping for \(randomTime)")
            Thread.sleep(forTimeInterval: randomTime) // Simulates intesnive computation
            let result = i // Simulate a result
            completionHandler(result)
        }
    }
}
print(taskRunner.getResults()) // Oh look, all the results are here! :D
...