同步 API 请求到异步 API 请求 Swift 2.2
Posted
技术标签:
【中文标题】同步 API 请求到异步 API 请求 Swift 2.2【英文标题】:Synchronous API request to Asynchronous API request Swift 2.2 【发布时间】:2016-11-12 10:25:42 【问题描述】:嗯,我是 Swift 新手,对完成处理程序了解不多。我想从 API 获取请求并解析 JSON 响应,以便获取令牌。但是我的代码发生的情况是,每当我调用 getAuthentication
函数时,我的 UI 都会冻结并等待获取数据。这是getAuthentication
的代码
func getAuthentication(username: String, password: String)
let semaphore = dispatch_semaphore_create(0);
let baseURL = "Some URL here"
let url = NSURL(string: baseURL)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = "\n \"username\": \"\(username)\",\n \"password\": \"\(password)\"\n".dataUsingEncoding(NSUTF8StringEncoding);
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) (data, response, error) -> Void in
if error == nil
let swiftyJSON = JSON(data: data!)
print(swiftyJSON)
//parse the data to get the user
self.id = swiftyJSON["id"].intValue
self.token = swiftyJSON["meta"]["token"].stringValue
else
print("There was an error")
dispatch_semaphore_signal(semaphore);
task.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
然后,我在我的 LoginViewController 中调用此方法。有人说我正在使用同步请求,这就是我的 UI 冻结的原因,但我真的不知道如何将其更改为异步并等待下载数据。有人可以帮我弄这个吗?任何帮助将不胜感激。
【问题讨论】:
结帐Alamofire。这是一个执行异步 HTTP 请求的便捷框架。 干脆去掉信号量;你正在用它阻塞主线程。您需要在完成闭包中处理响应 @Reginald,dataTaskWithRequest
这里使用的NSURLSession
函数是一个异步函数。此处无需使用dispatch_queue
。你可以看看我的回答。如有任何疑问,请随时发表评论
【参考方案1】:
首先,从你的函数中删除dispatch_semaphore
相关代码。
func getAuthentication(username: String, password: String)
let baseURL = "Some URL here"
let url = NSURL(string: baseURL)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = "\n \"username\": \"\(username)\",\n \"password\": \"\(password)\"\n".dataUsingEncoding(NSUTF8StringEncoding);
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) (data, response, error) -> Void in
if error == nil
let swiftyJSON = JSON(data: data!)
print(swiftyJSON)
//parse the data to get the user
self.id = swiftyJSON["id"].intValue
self.token = swiftyJSON["meta"]["token"].stringValue
else
print("There was an error")
task.resume()
在上面的代码中,函数dataTaskWithRequest
本身就是一个异步函数。因此,您不需要在后台线程中调用函数getAuthentication
。
对于添加完成处理程序,
func getAuthentication(username: String, password: String, completion:((sucess: Bool) -> Void))
let baseURL = "Some URL here"
let url = NSURL(string: baseURL)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = "\n \"username\": \"\(username)\",\n \"password\": \"\(password)\"\n".dataUsingEncoding(NSUTF8StringEncoding);
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) (data, response, error) -> Void in
var successVal: Bool = true
if error == nil
let swiftyJSON = JSON(data: data!)
print(swiftyJSON)
self.id = swiftyJSON["id"].intValue
self.token = swiftyJSON["meta"]["token"].stringValue
else
print("There was an error")
successVal = false
dispatch_async(dispatch_get_main_queue(), () -> Void in
completion(successVal)
)
task.resume()
可以这样调用:
self.getAuthentication("user", password: "password", completion: (success) -> Void in
)
【讨论】:
谢谢!这行得通!好吧,我忘记了 dispatch_async 这就是为什么即使我正在执行完成处理程序我也没有得到任何东西【参考方案2】:您可以将转义的闭包参数传递给 getAuthentication 方法。
func getAuthentication(username: String, password: String, completion: (JSON) -> ())
...
// create a request in the same way
...
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) (data, response, error) -> Void in
if error == nil
let swiftyJSON = JSON(data: data!)
print(swiftyJSON)
completion(swiftyJSON)
else
print("There was an error")
task.resume()
然后像这样在 LoginViewController 中调用 getAuthentication:
getAuthentication(username, password) (json) -> in
//Do whatever you want with the json result
dispatch_async(dispatch_get_main_queue())
// Do UI updates
另一种方法是在 LoginViewController 的后台线程中调用 getAuthentication 以避免阻塞主线程(即 UI 线程)。
//In LoginViewController
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
getAuthentication(username, password)
dispatch_async(dispatch_get_main_queue())
// UI updates
【讨论】:
以上是关于同步 API 请求到异步 API 请求 Swift 2.2的主要内容,如果未能解决你的问题,请参考以下文章