异步API请求Swift 2.2的同步API请求

时间:2016-11-12 10:25:43

标签: ios swift asynchronous swift2

我是Swift的新手,我对完成处理程序知之甚少。我想从API获取请求并解析JSON响应,以便我可以获取令牌。但是我的代码发生了什么,每当我调用<html> <head> <title>A Trello Dashboard</title> <link rel="stylesheet" media="screen" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body> <div class="container"> <h1>Trello Dashboard</h1> </div> </body> <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <script src="https://trello.com/1/client.js?key=mykey"></script> <script type="text/javascript"> Trello.authorize({ type: 'popup', name: 'A Trello Dashboard', scope: { read: 'true', write: 'true' }, expiration: 'never', success: function() { console.log("Successful authentication"); }, error: function() { console.log("Failed authentication"); } }); </script> </html> 函数时,我的UI就会冻结并等待数据获取。以下是getAuthentication

的代码
getAuthentication

然后,我在我的LoginViewController中调用此方法。有人说我正在使用同步请求,这就是我的用户界面冻结的原因,但我真的不知道如何将其更改为异步并等待数据下载。有人可以帮我弄这个吗?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

首先,从您的函数中删除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

})

答案 1 :(得分:1)

您可以将一个转义闭包参数传​​递给getAuthentication方法。

select * from Blog_CommentDetails
order by coalesce(ReplyCommentID, commentID), CommentID

在LoginViewController中调用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以避免阻塞主线程(即UI线程)。

getAuthentication(username, password) { (json) -> in
    //Do whatever you want with the json result
    dispatch_async(dispatch_get_main_queue()) {
        // Do UI updates
    }
}