Swift 关闭 API 连接
Swift close API connection
如果我使用这种方式连接到 API,是否会创建一个连接会话?以及如何关闭它以便下次运行时不会花费太多时间,因为还有另一个会话打开?!
do {
let data = try String(contentsOf: url)
if !data.isEmpty {
// use data
}
} catch {
print("Log \(error)")
}
更新
我的会话将从 API 中检索新闻,并根据这些新闻的经纬度在地图上绘制标记。 API 请求总是需要大约一秒钟,但在绘制标记之后需要不同的时间。当我导航到另一个视图然后返回到地图视图时,应用程序向 API 发送一个新请求并获取新的响应新闻标记。每次我导航回地图时,都需要更多时间来绘制标记这些是应用程序从开始 API 请求到标记完全绘制所花费的时间差:
第一次用时:7 秒
第二次用时:18 秒
第 3 次用时:30 秒
第 4 次用时:38 秒
第 5 次用时:49 秒
我试过task.suspend()
、task.cancel()
和session.invalidateAndCancel()
,但结果还是一样。
如何解决这个计时问题?
func getData() {
let urlString = URLFactory()
DispatchQueue.global(qos: .background).async {
// Set up the URL request
guard let url = URL(string: urlString.getWebserviceURL()) else {
NSLog("Log Error: cannot create URL")
self.processData()
return
}
let urlRequest = URLRequest(url: url)
if self.task != nil {
NSLog("Log suspend task")
self.task!.suspend()
}
// make the request
self.task = self.session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
NSLog("Log start task")
// check for any errors
guard error == nil else {
NSLog("Log error calling GET on webservice/getAllData: \(error!)")
self.processData()
return
}
// make sure we got data
guard let responseData = data else {
NSLog("Log Error: did not receive data")
self.processData()
return
}
// parse the result as JSON, since that's what the API provides
do {
guard let stringResponse = String(data: responseData, encoding: String.Encoding.utf8) else {
self.processData()
return
}
let json = JSON(parseJSON: stringResponse)
if (json["data"].arrayObject != nil) {
self.parse(json: json)
}
self.processData()
}
})
self.task!.resume()
}
}
private func processData() {
DispatchQueue.main.async {
if(!self.newsObj.isEmpty) {
self.drawMarker { () -> () in
self.stopActivityIndicator()
NSLog("Log Finished loading markers")
}
} else {
self.showToast(message: "No data found")
}
}
}
private func parse(json: JSON) {
newsObj.removeAll()
for data in json["data"].arrayValue {
// parse news data to newsObject
newsObj.append(news)
}
}
private func drawMarker(completion: (() -> ())) {
if mapView != nil {
mapView.clear()
startActivityIndicator("Loading Markers...")
for news in newsObj {
let marker = GMSMarker()
let listLatLng = news.getLatlong()
for latlng in listLatLng {
// Do stuff ...
}
}
marker.map = self.mapView
}
completion()
}
}
除非 url
只是一个本地文件,否则您真的不应该使用此方法。您应该在 URLSession
中执行此操作,方法如下:
let task = URLSession().dataTask(with: URL.init(string: "")!, completionHandler: {data, response, error in
if error != nil{
print("Log \(error)")
return //Stops the function
}
guard let data = data else{
return
}
guard let stringResponse = String(data: data, encoding: String.Encoding.utf8) else{
return
}
print("Log \(stringResponse)")
})
task.resume()
在上面的示例中,stringResponse
将数据保存为来自 URL 的字符串。
还要确保您使用的是 HTTPS,而不是 HTTP
如果我使用这种方式连接到 API,是否会创建一个连接会话?以及如何关闭它以便下次运行时不会花费太多时间,因为还有另一个会话打开?!
do {
let data = try String(contentsOf: url)
if !data.isEmpty {
// use data
}
} catch {
print("Log \(error)")
}
更新
我的会话将从 API 中检索新闻,并根据这些新闻的经纬度在地图上绘制标记。 API 请求总是需要大约一秒钟,但在绘制标记之后需要不同的时间。当我导航到另一个视图然后返回到地图视图时,应用程序向 API 发送一个新请求并获取新的响应新闻标记。每次我导航回地图时,都需要更多时间来绘制标记这些是应用程序从开始 API 请求到标记完全绘制所花费的时间差:
第一次用时:7 秒
第二次用时:18 秒
第 3 次用时:30 秒
第 4 次用时:38 秒
第 5 次用时:49 秒
我试过task.suspend()
、task.cancel()
和session.invalidateAndCancel()
,但结果还是一样。
如何解决这个计时问题?
func getData() {
let urlString = URLFactory()
DispatchQueue.global(qos: .background).async {
// Set up the URL request
guard let url = URL(string: urlString.getWebserviceURL()) else {
NSLog("Log Error: cannot create URL")
self.processData()
return
}
let urlRequest = URLRequest(url: url)
if self.task != nil {
NSLog("Log suspend task")
self.task!.suspend()
}
// make the request
self.task = self.session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
NSLog("Log start task")
// check for any errors
guard error == nil else {
NSLog("Log error calling GET on webservice/getAllData: \(error!)")
self.processData()
return
}
// make sure we got data
guard let responseData = data else {
NSLog("Log Error: did not receive data")
self.processData()
return
}
// parse the result as JSON, since that's what the API provides
do {
guard let stringResponse = String(data: responseData, encoding: String.Encoding.utf8) else {
self.processData()
return
}
let json = JSON(parseJSON: stringResponse)
if (json["data"].arrayObject != nil) {
self.parse(json: json)
}
self.processData()
}
})
self.task!.resume()
}
}
private func processData() {
DispatchQueue.main.async {
if(!self.newsObj.isEmpty) {
self.drawMarker { () -> () in
self.stopActivityIndicator()
NSLog("Log Finished loading markers")
}
} else {
self.showToast(message: "No data found")
}
}
}
private func parse(json: JSON) {
newsObj.removeAll()
for data in json["data"].arrayValue {
// parse news data to newsObject
newsObj.append(news)
}
}
private func drawMarker(completion: (() -> ())) {
if mapView != nil {
mapView.clear()
startActivityIndicator("Loading Markers...")
for news in newsObj {
let marker = GMSMarker()
let listLatLng = news.getLatlong()
for latlng in listLatLng {
// Do stuff ...
}
}
marker.map = self.mapView
}
completion()
}
}
除非 url
只是一个本地文件,否则您真的不应该使用此方法。您应该在 URLSession
中执行此操作,方法如下:
let task = URLSession().dataTask(with: URL.init(string: "")!, completionHandler: {data, response, error in
if error != nil{
print("Log \(error)")
return //Stops the function
}
guard let data = data else{
return
}
guard let stringResponse = String(data: data, encoding: String.Encoding.utf8) else{
return
}
print("Log \(stringResponse)")
})
task.resume()
在上面的示例中,stringResponse
将数据保存为来自 URL 的字符串。
还要确保您使用的是 HTTPS,而不是 HTTP