如何在URLSession中调用completionBlock

时间:2019-08-20 23:00:34

标签: swift urlsession

我正在尝试学习如何使用Rest API。我想先使用Github API从iPhone登录。

这是我的模型(尚未完成):

mutating func gettingAceess(completionBlock: @escaping (_ data : Data?, _ response : URLResponse?, _ error : Error?) -> Void ) throws {
    guard username != "", password != "" else {
        throw loginError.emptyUsernameOrPassword
    }

    let loginString = "\(self.username):\(self.password)"
    let resourceUrl = "https://\(loginString)@api.github.com"
    guard let loggingUrl = URL(string: resourceUrl) else {fatalError()}

    let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, response, error) in
        if error != nil {
            print("\(String(describing: error))")
        }
    }

    logging.resume()
}

在控制器中,我希望当用户点击登录按钮时,应该调用获取访问功能。

@IBAction func pressLoginBtn(_ sender: UIButton) {
    if let username = usernameInput.text,  let password = passwordInput.text {
        var logginInformation = LogginReguest(username: username, password: password)
        do {
            try logginInformation.gettingAceess(completionBlock: ...)
        } catch {
  }

try的代码前面,我不知道该写些什么。谁能帮我?还是我整个事情做错了?

2 个答案:

答案 0 :(得分:0)

do {
  // if completion block is last argument; you can use trailing syntax
  try logginInformation.gettingAceess() { (data, response, error) in
     // as your completion block have this signature
     // completionBlock: @escaping (_ data : Data?, _ response : URLResponse?, _ error : Error?) -> Void)

  }
} catch {

您还需要更新gettingAceess方法。

let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, response, error) in
  if error != nil {
     print("\(String(describing: error))")
   }
   // This line passes this completion block to caller who can read it
   completion(data, response, error)
}

上面的细节是您如何在示例中完成补全模块。建议不要直接通过URLSession完成块;宁愿处理它。

enum NKError: Error {
  case networkError
}

func gettingAceess(completionBlock: @escaping (Result<[String: Any], NKError>) -> Void ) {
  let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, response, error) in
    if error != nil {
      print("\(String(describing: error))")
      completion(.failure(NKError.networkError))
    }

    // Now I can check for status or data
    if let data = data {
      // parse the result and then return
      if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
        completion(.success(json))
      }
    }
  }
}

在这种情况下,我试图将errorjson传递给呼叫者。

答案 1 :(得分:0)

您的方法是错误的。首先,在调用异步任务之前已经检查了空文本字段。

第二个坏习惯是使包含异步任务的函数throws在完成块中返回接收到的数据或错误。

这是一个示例,其中Result结构返回接收的Data作为字符串或错误。

mutating func gettingAccess(completionBlock: @escaping (Result<String,Error>) -> Void)
{
    let loginString = "\(self.username):\(self.password)"
    let resourceUrl = "https://\(loginString)@api.github.com"
    guard let loggingUrl = URL(string: resourceUrl) else {fatalError()}

    let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, _, error) in
        if let error = error {
            completion(.failure(error))
        } else {
            let string = String(data: data!, encoding: .utf8)!
            completion(.success(string))
        }
    }

    logging.resume()
}

@IBAction func pressLoginBtn(_ sender: UIButton) {
    guard usernameInput.hasText, passwordInput.hasText else { 
       // show an alert
       return
    }
    let logginInformation = LogginReguest(username: usernameInput.text!, password: passwordInput.text!)
    logginInformation.gettingAccess { result in
        switch result {
        case .success(let string): print(string)
        case .failure(let error): print(error)

        }
    } 
  }

旁注:

请寻找当代教程。带有参数标签和下划线的(_ data : Data?, _ response : URLResponse?, _ error : Error?)语法是Swift 2旧式语法。