执行 segue 时的异步检查

Async checking when perform segue

我的应用有两个 ViewController,LoginViewController,MainViewController

在故事板中,我创建了一个从 LoginViewController 到 MainViewController 的 segue

现在我用Moya来实现登录功能,但是我想保留segue

所以我在LoginViewController中写了这个函数

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    var ret = false
    let provider = MoyaProvider<MyApi>()
    provider.request(.login(username : inUsername.text! , password : inPassword.text! )) { result in
        switch result {
        case let .success(moyaResponse):
            let data = moyaResponse.data
            do {
                let decoder = JSONDecoder()
                let user = try decoder.decode(Login.self, from: data)
                if(user.status == 1){
                    ret = true
                }else{
                    print(user.msg)
                }
            }
            catch {
                print("error")
            }
        case let .failure(error):
            ret = false
        }
    }
    return ret
}

但是 moya 请求是异步的,这个函数会 return 在响应之前,所以这个函数永远不会 return true

如何进行这项工作?


更新:

现在我将请求移至按钮 IBAction,但它仍然不起作用

如果我删除 shouldPerformSegue,它仍然会在回调

之前转到下一个 viewcontroller

如果我 return 在 shouldPerformSegue 中为真,它将转到下一个 viewcontroller 即使登录失败

如果我在shouldPerformSegue中return false,它不会进入下一个viewcontroller即使登录成功

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    return true // always to next 
    return false // never to next 
}

@IBAction func clickLogin(_ sender: Any) {

    let provider = MoyaProvider<ZfuApi>()
    provider.request(.login(username : inUsername.text! , password : inPassword.text! )) { result in
        switch result {
        case let .success(moyaResponse):
            let data = moyaResponse.data
            do {
                let decoder = JSONDecoder()
                let user = try decoder.decode(Login.self, from: data)
                if(user.status == 1){
                    self.performSegue(withIdentifier: "loginToMain", sender: sender)
                }else{
                    print(user.msg)
                }
            }
            catch {
                print("error")
            }
        case let .failure(error):
            print(error.response?.description)
        }
    }
}

你不能在 shouldPerformSegue 中使用异步方法,但你可以在执行 segue 之前执行异步方法,然后在完成块中调用 performSegue(withIdentifier:sender:)

您可以引入一个 属性 来执行 segue,如下所示,

var isLoggedIn: Bool = false {
    didSet {
        self.performSegue(withIdentifier: "loginToMain", sender: self)
    }
}

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    return isLoggedIn
}

@IBAction func clickLogin(_ sender: Any) {

    let provider = MoyaProvider<ZfuApi>()
    provider.request(.login(username : inUsername.text! , password : inPassword.text! )) { result in
        switch result {
        case let .success(moyaResponse):
            let data = moyaResponse.data
            do {
                let decoder = JSONDecoder()
                let user = try decoder.decode(Login.self, from: data)
                if(user.status == 1){
                    self.isLoggedIn = true
                }else{
                    print(user.msg)
                }
            }
            catch {
                print("error")
            }
        case let .failure(error):
            print(error.response?.description)
        }
    }
}