【问题标题】:http request completion handler and closure firing before completion of the responsehttp请求完成处理程序和响应完成之前的关闭触发
【发布时间】:2021-10-31 22:57:29
【问题描述】:

所以我目前遇到的问题是关闭在请求响应完成之前触发。

我已经实现了一个完成处理程序和闭包,我不确定我是否做错了,或者我调用函数的方法是否不正确。

这里是包含完成处理程序的请求。

func ElevationRequest(listOfPointsToQuery: Array<CLLocationCoordinate2D>, success:Bool,completeHandler: (Bool) -> Void){
        var processedQueryPoints = Array<String>() //points which have been ordered based on the execution order are stored here
        var newStringCoordinate = String() // the next coordinates are stored here temporarily
        var finalStringConvertedCoordinates = String()
        var jsonResponse = String()
        for i in 0..<listOfPointsToQuery.count{ //go through all listed points to be queried within the http request sent to googles elevation api - returned as a json format dictionary
            var latHolder = String(listOfPointsToQuery[i].latitude)
            var lonHolder = String(listOfPointsToQuery[i].longitude)
            newStringCoordinate = latHolder + "," + lonHolder
            processedQueryPoints.append(newStringCoordinate)
                    }
        finalStringConvertedCoordinates = processedQueryPoints.joined(separator: "%7C") //google documentation demonstrates the use of the pipe ("|") - using pipe causes errors and the function will not.. function. "%7C" is used in its place
        let apiKey = "AIzaSyAPqcl47sO5eJIkdl46Ww-uJLgv_7aJq3I"
        print(finalStringConvertedCoordinates)
        struct ElevationResponse: Decodable {
            let results: [ElevationResult]
        }
        struct ElevationResult: Decodable {
             let elevation: Double
             let location: LatLngLiteral
             let resolution: Double?
            
        enum resultKeys: String, CodingKey {
            case results = "results"
            case elevation = "elevation"
            case location = "location"
            case resolution = "resolution"
            case lat = "lat"
            case lon = "lon"
            }
        }
        struct LatLngLiteral: Decodable {
             let lat: Double
             let lng: Double
        }
        guard let url = URL(string: "https://maps.googleapis.com/maps/api/elevation/json?&locations=\(finalStringConvertedCoordinates)&key=\(apiKey)") else {
                    print("Error: cannot create URL")
                    return
                }
                // Create the url request
                var request = URLRequest(url: url)
                request.httpMethod = "GET"
                let task = URLSession.shared.dataTask(with: request) { [self] data, response, error in
                    guard error == nil else {
                        print("Error: error calling GET")
                        print(error!)
                        return
                    }
                    guard let data = data else {
                        print("Error: Did not receive data")
                        return
                    }
                    //print("---> data: \(String(data: data, encoding: .utf8))")
                    guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else {
                        print("Error: HTTP request failed")
                        return
                    }
                    do {
                        guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                            print("Error: Cannot convert data to JSON object")
                            return
                        }
                        guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
                            print("Error: Cannot convert JSON object to Pretty JSON data")
                            return
                        }
                        guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8)
                        else {
                            print("Error: Could print JSON in String")
                            return
                        }
                        //print(prettyPrintedJson)
                        jsonResponse = prettyPrintedJson
                    } catch {
                        print("Error: Trying to convert JSON data to string")
                        return
                    }
                    let decoder = JSONDecoder()
                    let jrData = jsonResponse.data(using: .utf8)
                    let jsonResponseProcessed = try! decoder.decode(ElevationResponse.self, from: jrData!)

            for i in 0..<listOfPointsToQuery.count{
                        processedElevation.append(jsonResponseProcessed.results[i].elevation)
                        print(processedElevation)
                        print("processed elevation data ^")
            }
            }
        task.resume()
        completeHandler(success)
    } 

闭包是在这个函数定义之后立即定义的。

var completehandler:(Bool)->Void = { (sucess) in
        if sucess {
            print("Complete download data ")
                altitudeAdjustmentViaElevationData(elevationPointsList: processedElevation)
        } else {
            print("Error")
        }
        
    }

函数终于被这样调用了。

ElevationRequest(listOfPointsToQuery: finalAutoPathPoints, success: true, completeHandler: completehandler) 

最后一点似乎值得一提。我没有经验,所以我不确定这是否有任何相关性。

我正在与调用相同的函数中处理 json 响应。该代码包含在上面的第一个代码段中,控制台响应如下所示。

Complete download data 
[11.59268283843994]
processed elevation data ^
[11.59268283843994, 11.68190288543701]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947, 11.79109859466553]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947, 11.79109859466553, 11.35733222961426]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947, 11.79109859466553, 11.35733222961426, 11.57364559173584]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947, 11.79109859466553, 11.35733222961426, 11.57364559173584, 11.7429027557373]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947, 11.79109859466553, 11.35733222961426, 11.57364559173584, 11.7429027557373, 12.02133083343506]
processed elevation data ^
[11.59268283843994, 11.68190288543701, 11.86490249633789, 11.53255939483643, 11.46291351318359, 11.69645023345947, 11.79109859466553, 11.35733222961426, 11.57364559173584, 11.7429027557373, 12.02133083343506, 11.66207313537598]
processed elevation data ^ ```

【问题讨论】:

  • 你必须调用completeHandler inside闭包。将最后两个 } 之间的行向上移动。而不是使用JSONSerializtion 进行不必要的转换,而是捕获JSONDecoder 的错误。 DecodingError 非常具有描述性。
  • @vadian 嗨,谢谢您的回复。取消那个。我认为它现在固定了。非常感谢。
  • 请格式化您的代码。在 Xcode 中按 ⌘A 和 ⌃I。将completeHandler: 替换为completeHandler: @escaping
  • 谢谢 如果你不介意你能告诉我为什么我在使用闭包激活函数调用时会遇到这个问题。 (实例成员 'altitudeAdjustmentViaElevationData' 不能用于类型 'MapViewController';您的意思是改用这种类型的值吗?)。 (实例成员 'processedElevation' 不能用于类型 'MapViewController';您的意思是改用这种类型的值吗?)
  • 如果您愿意,请回复答案

标签: json swift http httprequest completionhandler


【解决方案1】:

感谢@vidian 帮助回答了这个问题。

关于http请求响应完成之前执行的问题,这个问题的根源在于我对完成请求的处理失误。

第一个代码段的尾部是这样的。

       }
            }
        task.resume()
        completeHandler(success)
    }  

它应该是这样的结构。

       }
       completeHandler(success)
            }
        task.resume()
    } 

我编写的代码中的另一个问题是没有正确定义闭包。将其定义为函数解决了这个问题。正确的闭包定义如下。

 func completehandler(_ sucess : Bool) {
        if sucess {
            print("Complete download data ")
               AltitudeAdjustmentViaElevationData(elevationPointsList: processedElevation)
        } else {
            print("Error")
        }
        
    } 

【讨论】:

    猜你喜欢
    • 2019-11-16
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多