http 请求完成处理程序和关闭响应完成之前触发
http request completion handler and closure firing before completion of the response
所以我目前遇到的问题是闭包在请求响应完成之前触发。
我已经实现了一个完成处理程序和闭包,我不确定我是否做错了,或者我调用函数的方法是否不正确。
这里是包含完成处理程序的请求。
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 ^ ```
感谢@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")
}
}
所以我目前遇到的问题是闭包在请求响应完成之前触发。
我已经实现了一个完成处理程序和闭包,我不确定我是否做错了,或者我调用函数的方法是否不正确。
这里是包含完成处理程序的请求。
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 ^ ```
感谢@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")
}
}