执行 segue 时的异步检查

Posted

技术标签:

【中文标题】执行 segue 时的异步检查【英文标题】:Async checking when perform segue 【发布时间】:2018-10-04 07:41:06 【问题描述】:

我的应用有两个 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请求是异步的,这个函数会在响应之前返回,所以这个函数永远不会返回true

如何做到这一点?


更新:

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

如果我删除shouldPerformSegue,它仍然会在回调之前转到下一个视图控制器

如果我在shouldPerformSegue 中返回true,即使登录失败也会转到下一个视图控制器

如果我在shouldPerformSegue中返回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)
        
    

【问题讨论】:

将此请求移至某个登录按钮处理程序。一旦你得到状态然后执行segue 在登录按钮IBAction 中执行异步请求。当请求回调并登录成功时,调用self.performSegue(withIdentifier:sender:) 我添加了一个基于当前实现的答案。可以试试吗? 【参考方案1】:

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

【讨论】:

这行不通,现在我将请求移至 IBAction ,但我应该在shouldPerformSegue 中返回什么?如果我返回 ture,它总是进入下一个视图,如果我返回 false,它永远不会进入下一个视图 @Ilya-Kharabet 的建议是正确的。 shouldPerformSegue 最好用于停止已在情节提要文件中以编程方式定义的 segue,否则它们将始终执行,正如您所注意到的。另一种方法是在情节提要中定义 segue,不是从控件到新视图控制器,而是从控制器到控制器,然后只能在代码中激活。然后,在您的异步代码中,执行您在shouldPerformSegue() 中的检查。如果通过,您可以通过使用performSegue() 调用segue 来手动执行segue。 现在好了,我只是去掉按钮segue,然后从控制器创建一个新的segue,然后一切正常。【参考方案2】:

您可以引入一个属性来执行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)
        
    

【讨论】:

是的,我试过了,这个没问题,但最后我用controller to controller segue,因为这样更好。 没错,这是更好的方法。

以上是关于执行 segue 时的异步检查的主要内容,如果未能解决你的问题,请参考以下文章

iOS8 UITableView 和 Cell - 自动布局高度 - 触摸和执行 segue 时的移位/垂直偏移错误

如何根据来自另一个线程的 JSON 结果确定是不是执行 segue

在 ViewDidLoad 上执行 Segue

从 viewDidLoad() 执行 Segue

Segue 没有在 viewController 中执行

如何检查使用了哪个 segue