Search code examples
swiftsegueuistoryboardseguemoya

Async checking when perform segue


My app has two ViewControllers, LoginViewController, MainViewController

In storyboard, I have created a segue from LoginViewController to MainViewController

And now I use Moya to implement the login function, but I want to keep the segue

So I write this function in 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
}

But moya request is async, this function will return before response, so this function never return true

How to make this work?


update:

Now I move the request to button IBAction, but it still not work

if I remove shouldPerformSegue, it still go to next viewcontroller before callback

if I return true in shouldPerformSegue, it will go to next viewcontroller even login fail

if I return false in shouldPerformSegue, it will not go to next viewcontroller even login success

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)
        }
    }
}

Solution

  • You can't use async method in shouldPerformSegue, but you can perform async method before performing segue and than call performSegue(withIdentifier:sender:) in completion block.