从DispatchQueue内部快速返回

时间:2020-03-31 18:18:31

标签: ios swift asynchronous

我正在构建一个函数,该函数需要一个CLLocation参数,并返回我自己定义的DarkSkyResponse类型的天气预报。

public func getForecast(at location: CLLocation) -> DarkSkyResponse {
    let request = DarkSkyRequest(key: "KEYGOESHERE")
    let point = DarkSkyRequest.Point(location.coordinate.latitude, location.coordinate.longitude)

    guard let url = request.buildURL(point: point) else {
        preconditionFailure("Failed to construct URL")
    }

    let task = URLSession.shared.dataTask(with: url) {
        data, response, error in

        DispatchQueue.main.async {
            guard let data = data else {
                fatalError("No Data Recieved")
            }
            guard let forecast = DarkSkyResponse(data: data) else {
                fatalError("Decoding Failed")
            }
            return forecast
        }
    }
    task.resume()
}

一切正常,我只想返回DispatchQueue中的forecast变量。当我尝试执行此操作时,遇到以下错误: Unexpected non-void return value in void function 我相信这是因为我正在DispatchQueue内部返回。

为解决此问题,我将数据任务和解码过程移入了具有完成处理程序的自身函数中。当我调用该函数时,只需将闭包设置为按以下方式返回输出:

public func getForecast(at location: CLLocation) -> DarkSkyResponse {
    let request = DarkSkyRequest(key: "KEYGOESHERE")
    let point = DarkSkyRequest.Point(location.coordinate.latitude, location.coordinate.longitude)

    guard let url = request.buildURL(point: point) else {
        preconditionFailure("Failed to construct URL")
    }

    func getDataAndDecode(from url: URL, completionBlock: @escaping (DarkSkyResponse) -> Void) -> Void {
        let task = URLSession.shared.dataTask(with: url) {
            data, response, error in

            DispatchQueue.main.async {
                guard let data = data else {
                    fatalError("No Data Recieved")
                }
                guard let forecast = DarkSkyResponse(data: data) else {
                    fatalError("Decoding Failed")
                }
                completionBlock(forecast)
            }
        }
        task.resume()
    }

    getDataAndDecode(from: url) { (output) in
        return output
    }
}

现在我得到一条警告:Expression of type 'DarkSkyResponse' is unused。我正在以正确的方式执行此操作,还是有一种更优雅的方式来返回我想要的值?

1 个答案:

答案 0 :(得分:2)

就目前而言,swift尚不支持异步等待样式(类似于javascript),这意味着您无法直接从异步操作中返回。 最好将callback(completionBlock)参数放在 getForecast 方法中。如果回调函数还处理错误情况(例如 onSuccess onError ),那将是很好的选择。并且不要忘记将getForecast方法设置为void方法。

所以就像这样:


func getForecast(at location: CLLocation, onSuccess: (DarkSkyResponse) -> (), onError: (Error) -> ()) {

...
}