Ios 如何在Swift中处理异步http请求
我有以下代码:Ios 如何在Swift中处理异步http请求,ios,swift,Ios,Swift,我有以下代码: func mapView(_ mapView: MGLMapView, annotation: MGLAnnotation, calloutAccessoryControlTapped control: UIControl) { var bus = [String]() let headers = [ "content-type": "application/x-www-form-urlencoded", "cache-contro
func mapView(_ mapView: MGLMapView, annotation: MGLAnnotation, calloutAccessoryControlTapped control: UIControl) {
var bus = [String]()
let headers = [
"content-type": "application/x-www-form-urlencoded",
"cache-control": "no-cache",
"postman-token": "23cb4108-e24b-adab-b979-e37fd8f78622"
]
let postData = NSMutableData(data: "bus_stop=Science Hill".data(using: String.Encoding.utf8)!)
let request = NSMutableURLRequest(url: NSURL(string: "https://ucsc-bts3.soe.ucsc.edu/bus_stops/inner_eta.php?%22bus_stop%22=%22Science%20Hill%22")! as URL,
cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error!)
} else {
_ = response as? HTTPURLResponse
}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!)
guard let jsonArray = jsonObject as? [String: Any] else{
print("JsonSerialization Failed")
return
}
if let etaTableRows = jsonArray["rows"] as? NSArray{
for etaData in etaTableRows{
let etaDictionary = etaData as? NSDictionary
bus.append(etaDictionary!["bus_type"] as! String)
}
}
} catch {
print("JSONSerialization error:", error)
}
})
dataTask.resume()
print(bus) //bus array should be updated here
mapView.deselectAnnotation(annotation, animated: false)
let schedule = ScheduleVC()
schedule.data.append(annotation.title!! + " ETAs")
self.present(schedule, animated: true, completion: nil)
}
在收到http响应并填充总线阵列之前,似乎正在运行打印(总线)。我的目标是用http响应数据填充总线阵列,然后打印它。我不知道如何做到这一点。我建议您阅读《什么是
异步》
为了理解程序员的误解,让我们看看他是如何理解的
他认为密码是正确的。他认为代码的运行顺序如下:
您需要传递callback,并在asynchronous
call中调用callback
例如:
class func getBusArray(completionHandler: (bus: NSArray) -> ()) {
...
let task = session.dataTaskWithURL(url) {
data, response, error in
...
resultsArray = results
completionHandler(bus: resultsArray)
}
...
task.resume()
}
你可以这样打电话
override func viewDidLoad() {
MyModel.getBusArray {
bus in
println("Response: \(bus)")
}
}
我建议您阅读,什么是
异步
为了理解程序员的误解,让我们看看他是如何理解的
他认为密码是正确的。他认为代码的运行顺序如下:
您需要传递callback,并在asynchronous
call中调用callback
例如:
class func getBusArray(completionHandler: (bus: NSArray) -> ()) {
...
let task = session.dataTaskWithURL(url) {
data, response, error in
...
resultsArray = results
completionHandler(bus: resultsArray)
}
...
task.resume()
}
你可以这样打电话
override func viewDidLoad() {
MyModel.getBusArray {
bus in
println("Response: \(bus)")
}
}
在这种特殊情况下,解决方案非常简单: 在接收到闭包内的数据后运行代码 这很快:不要使用
NSURL
,NSMutableData
,NSMutableURLRequest
,NSArray
和NSDictionary
func mapView(_ mapView: MGLMapView, annotation: MGLAnnotation, calloutAccessoryControlTapped control: UIControl) {
var bus = [String]()
let headers = [
"content-type": "application/x-www-form-urlencoded",
"cache-control": "no-cache",
"postman-token": "23cb4108-e24b-adab-b979-e37fd8f78622"
]
let postData = Data("bus_stop=Science%20Hill".utf8)
var request = URLRequest(url: URL(string: "https://ucsc-bts3.soe.ucsc.edu/bus_stops/inner_eta.php?%22bus_stop%22=%22Science%20Hill%22")!,
cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData
let session = URLSession.shared
let dataTask = session.dataTask(with: request, completionHandler: { (data, response, error) in
if let error = error {
print(error); return
}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!)
guard let jsonArray = jsonObject as? [String: Any] else {
print("JsonSerialization Failed")
return
}
if let etaTableRows = jsonArray["rows"] as? [[String:Any]] {
for etaData in etaTableRows {
bus.append(etaData["bus_type"] as! String)
}
print(bus)
self.mapView.deselectAnnotation(annotation, animated: false)
let schedule = ScheduleVC()
schedule.data.append(annotation.title!! + " ETAs")
self.present(schedule, animated: true, completion: nil)
}
} catch {
print("JSONSerialization error:", error)
}
})
dataTask.resume()
}
在这种特殊情况下,解决方案非常简单: 在接收到闭包内的数据后运行代码 这很快:不要使用
NSURL
,NSMutableData
,NSMutableURLRequest
,NSArray
和NSDictionary
func mapView(_ mapView: MGLMapView, annotation: MGLAnnotation, calloutAccessoryControlTapped control: UIControl) {
var bus = [String]()
let headers = [
"content-type": "application/x-www-form-urlencoded",
"cache-control": "no-cache",
"postman-token": "23cb4108-e24b-adab-b979-e37fd8f78622"
]
let postData = Data("bus_stop=Science%20Hill".utf8)
var request = URLRequest(url: URL(string: "https://ucsc-bts3.soe.ucsc.edu/bus_stops/inner_eta.php?%22bus_stop%22=%22Science%20Hill%22")!,
cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData
let session = URLSession.shared
let dataTask = session.dataTask(with: request, completionHandler: { (data, response, error) in
if let error = error {
print(error); return
}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!)
guard let jsonArray = jsonObject as? [String: Any] else {
print("JsonSerialization Failed")
return
}
if let etaTableRows = jsonArray["rows"] as? [[String:Any]] {
for etaData in etaTableRows {
bus.append(etaData["bus_type"] as! String)
}
print(bus)
self.mapView.deselectAnnotation(annotation, animated: false)
let schedule = ScheduleVC()
schedule.data.append(annotation.title!! + " ETAs")
self.present(schedule, animated: true, completion: nil)
}
} catch {
print("JSONSerialization error:", error)
}
})
dataTask.resume()
}
一些意见:
NSMutableData
(使用Data
)、NSMutableURLRequest
(使用URLRequest
)、NSURL
(使用URL
)、NSArray
、NSDictionary
,等等。通常最好尽可能保留在Swift类型中JSONDecoder
而不是手动遍历JSONSerialization
结果bus_stop=Science Hill
在x-www-form-urlrequest
中无效。看NSMutableData
(使用Data
)、NSMutableURLRequest
(使用URLRequest
)、NSURL
(使用URL
)、NSArray
、NSDictionary
,等等。通常最好尽可能保留在Swift类型中JSONDecoder
而不是手动遍历JSONSerialization
结果bus_stop=Science Hill
在x-www-form-urlrequest
中无效。看extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
return allowed
}()
}