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