我想使用转义关闭来执行一些代码,但它无法正常工作。你能告诉我这个例子有什么问题吗?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("Calling getData")
getData(completion: {
print("Escaping closure getData")
})
print("Returning from getData")
print("Calling doSomething")
doSomething (completion: {
print("Escaping closure doSomething")
})
print("Returning from doSomething")
}
func getData(completion: @escaping () ->Void)
{
print ("Begin getData")
var request = URLRequest(url: URL(string: "https://jsonplaceholder.typicode.com")!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
print ("Escaping closure dataTask")
guard error == nil else {
print("Error calling GET API: \(error!)")
return
}
}
task.resume()
print ("Ending getData")
}
func doSomething(completion: @escaping () ->Void)
{
print ("Begin doSomething")
sleep(3)
print ("Ending doSomething")
}
}
print("Escaping closure getData")
和print("Escaping closure doSomething")
永远不会被执行。
答案 0 :(得分:1)
主要问题是你从未真正调用函数内的闭包。
func getData(completion: @escaping () ->Void){
print ("Begin getData")
var request = URLRequest(url: URL(string: "https://jsonplaceholder.typicode.com")!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
print ("Escaping closure dataTask")
guard error == nil else {
print("Error calling GET API: \(error!)")
return
}
print ("Ending getData")
completion()
}
task.resume()
}
其他一些通用问题:print ("Ending getData")
应该在URLSession.dataTask(with:)
的完成处理程序中,否则它将在网络请求实际完成执行之前被调用。
您不应该使用sleep()
,因为它也会阻止主线程,因此会使您的整个应用无响应。
您很少想要空的完成处理程序。你通常会实现的是一个带有两个或多个可选输入参数的闭包,每个返回值一个,错误一个。
func getData(completion: @escaping (Data?,Error?) ->Void){
var request = URLRequest(url: URL(string: "https://jsonplaceholder.typicode.com")!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
guard error == nil, let data = data else {
completion(nil,error)
return
}
//In general you would also convert `data` into a more suitable format, in your case, you would deserialize the JSON
completion(data,nil)
}
task.resume()
}
然后这样称呼:
getData({ data, error in
guard error == nil, let data = data else {
//handle the error here
return
}
//use the value from the network request
})
答案 1 :(得分:0)
完成异步任务后,您必须调用completion
个关闭。例如,您的getData
应该更像这样:
func getData(completion: @escaping () ->Void) {
print ("Begin getData")
var request = URLRequest(url: URL(string: "https://jsonplaceholder.typicode.com")!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
print ("Escaping closure dataTask")
guard error == nil else {
print("Error calling GET API: \(error!)")
completion() //-------Here, before returning
return
}
completion() //--------Here, after your task is done (and error free)
}
task.resume()
print ("Ending getData")
}