为什么在快速返回值时出现“在void函数中出现非预期的非空返回值”错误?

问题描述

尽管我在函数中提供了返回类型,但我收到了错误“ void函数中出现非预期的非空返回值”。

以下是我的参考代码

func getLatDestination() -> Double {
    var params = [String: Any]()
    params[ParametersKeys.access_token] = KeyChain.getAccesstoken()!
    params[ParametersKeys.address] = googlePlaceObject?.results.first?.formattedAddress
    params[ParametersKeys.latitude] = googlePlaceObject?.results.first?.geometry.location.lat
    params[ParametersKeys.longitude] = googlePlaceObject?.results.first?.geometry.location.lng
    params[ParametersKeys.googlePlaceId] = googlePlaceObject?.results.last?.placeId
    params[ParametersKeys.login_type] = 1
        
    AuthManager.shared.saveAddressAsWorkHome(params) { (response) in
        if response.flag == RESPONSE_FLAGS.flag_143 {
            if let addressData = response.response["addresses"] as? [[String: Any]] {
                return  addressData[0]["lat"]
            }
        }
    }
}

在控制台中,我得到addressData[0]["lat"]的价值是Optional(51.5050755)

请问我这是一个非常基本的问题,因为我是新手。

解决方法

我认为AuthManager.shared.saveAddressAsWorkHome(params) { (response) in这是asynchronous的闭包,您正在尝试在其中返回一个值,以便得到此错误。

您不能直接从异步函数返回。您必须在方法上添加完成处理程序,并从完成处理程序中的异步返回值

所以您必须更改功能

func getLatDestination(completion : @escaping (Double) -> ()){
var params = [String: Any]()
params[ParametersKeys.access_token] = KeyChain.getAccessToken()!
params[ParametersKeys.address] = googlePlaceObject?.results.first?.formattedAddress
params[ParametersKeys.latitude] = googlePlaceObject?.results.first?.geometry.location.lat
params[ParametersKeys.longitude] = googlePlaceObject?.results.first?.geometry.location.lng
params[ParametersKeys.googlePlaceId] = googlePlaceObject?.results.last?.placeId
params[ParametersKeys.login_type] = 1
    
AuthManager.shared.saveAddressAsWorkHome(params) { (response) in
    if response.flag == RESPONSE_FLAGS.flag_143 {
        if let addressData = response.response["addresses"] as? [[String: Any]] {
                    completion(addressData[0]["lat"])

        }
    }
}

当您调用函数时

getLatDestination(completion: {ret in
        print(ret) 
    })
,

您无法做您想做的事情。函数saveAddressAsWorkHome()是异步的。调用它时,它将在结果可用之前立即返回。在将来的某个时间,保存完成并且您的完成处理程序代码被执行。

您不能从完成处理程序中的函数中返回。

您需要重构getLatDestination()函数以使用完成处理程序,并在结果可用时调用它。

您应该阅读Swift中的异步函数和完成处理程序。

重写后的函数可能如下所示:

func getLatDestination(completion: @escaping (Double?)->())  {
    var params = [String: Any]()
    params[ParametersKeys.access_token] = KeyChain.getAccessToken()!
    params[ParametersKeys.address] = googlePlaceObject?.results.first?.formattedAddress
    params[ParametersKeys.latitude] = googlePlaceObject?.results.first?.geometry.location.lat
    params[ParametersKeys.longitude] = googlePlaceObject?.results.first?.geometry.location.lng
    params[ParametersKeys.googlePlaceId] = googlePlaceObject?.results.last?.placeId
    params[ParametersKeys.login_type] = 1
        
    AuthManager.shared.saveAddressAsWorkHome(params) { (response) in
        if response.flag == RESPONSE_FLAGS.flag_143 {
            if let addressData = response.response["addresses"] as? [[String: Any]] {
                completion(addressData[0]["lat"] as? Double)
            }
        }
        else { completion(nil) }
    }
}

函数`getLatDestination()现在带有一个完成处理程序,即一段代码。反过来,该完成处理程序将使用Optional Double作为结果。 (看来您的异步函数返回了一个字典,您不能确保它会包含您期望的键/值和类型。