首页 > 解决方案 > Swift:保持代码执行,直到收到 API 响应

问题描述

我需要设置授权屏幕:

1) 登录并输入密码

2) 应用程序从 API 请求令牌

3) 收到响应

4)App检查响应是否包含令牌:如果包含,应该执行授权

要解决的问题:应用程序在步骤 3) 之前生成 4)

我尝试了什么:我使用转义闭包来保持执行,直到接收到 API 数据,但它只起到了部分作用——它只有助于保持对令牌的赋值,但我仍然不能保持“如果检查”。

    override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    if identifier == "loginSegue" {

        let login = loginInput.text!
        let password = passInput.text!

        tokenLoader.getToken(login: login, password: password) { [weak self] token in
            self?.token = token.access_token
        }

        //THIS CODE I NEED TO HOLD UNTIL DATA FROM API RECEIVED
        if token != "" {
            return true
        } else {
            let alert = UIAlertController(title: nil, message: "Incorrect password", preferredStyle: .alert)
            let action = UIAlertAction(title: "OK", style: .cancel, handler: nil)
            alert.addAction(action)
            present(alert, animated: true, completion: nil)
            return false
        }
        //

    } else {
        return true
    }
}
    class TokenLoader {
    let session = Session.instance
    let baseUrl = "http://46.254.18.193:9096"

    func getToken(login: String, password: String, completion: @escaping (AccessToken) -> Void) {
        let path = "/token"
        let parameters: Parameters = [
            "grant_type": "client_credentials",
            "client_id": login,
            "client_secret": password,
            "scope": "read"
        ]
        let url = baseUrl+path
        AF.request(url, method: .get, parameters: parameters).responseData { response in

            do {
                let token = try JSONDecoder().decode(AccessToken.self, from: response.value!)
                print(token)
                self.session.token = token.access_token
                completion(token)

            } catch {
                print(error)
            }
        }
    }
}

标签: swiftapiconcurrencyclosures

解决方案


您可以使用此功能解决问题......当您想要 segue 或获取令牌时在事件上执行它

func getTokenAndPerformSegue() {
    let login = loginInput.text
    let password = passInput.text

    if let getLogin = login ,let getPassword = password {

    tokenLoader.getToken(login: getLogin, password: getPassword) { [weak self] token in
           self?.token = token.access_token

        if token.isEmpty() {
            let alert = UIAlertController(title: nil, message: "Incorrect password", preferredStyle: .alert)
            let action = UIAlertAction(title: "OK", style: .cancel, handler: nil)
            alert.addAction(action)
            present(alert, animated: true, completion: nil)
        } else {
             performSegue(withIdentifier: "loginSegue", sender: nil)
        }

       }
    }

}

你需要这样写...在完成时返回 nil 或错误

 func getToken(login: String, password: String, completion: @escaping (AccessToken?) -> Void) {
        let path = "/token"
        let parameters: Parameters = [
            "grant_type": "client_credentials",
            "client_id": login,
            "client_secret": password,
            "scope": "read"
        ]
        let url = baseUrl+path
        AF.request(url, method: .get, parameters: parameters).responseData { response in

            do {
                let token = try JSONDecoder().decode(AccessToken.self, from: response.value!)
                print(token)
                self.session.token = token.access_token
                completion(token)

            } catch {
                completion(nil)
                print(error)
            }
        }
    }

如果您没有得到任何东西或者您需要进一步的帮助,请告诉我


推荐阅读