从线程/ GCD/完成处理程序返回

Posted

技术标签:

【中文标题】从线程/ GCD/完成处理程序返回【英文标题】:Returning from threading/ GCD/ completion handler 【发布时间】:2018-11-18 02:06:14 【问题描述】:

我有一些逻辑可以让用户从登录屏幕登录。如果登录失败,我想显示一条消息让用户知道。如果用户登录成功,我会触发一个 segue。当我使用无效凭据对其进行测试时,错误警报会按预期显示,但即​​使它嵌套在 if-else 语句中,segue 仍会被触发。为什么是这样?我怎样才能退出它并避免 else 块......?我尝试在 DispatchQ/show alert 代码下添加“return”,但没有任何效果。

self.login(username: usernameTextField.text!, password: passwordTextField.text!)  (error) in
        if error != nil 
            DispatchQueue.main.async 
                self.showAlert(msg: error ?? "error")
            
         else 
            DispatchQueue.main.async 
                // segue code
            
        
    

登录:

func login(username: String, password: String, completionHandler: @escaping (_ error: String?) -> ()) 
    SessionHelper.shared.logUserIn(withUsername: username, andPassword: password)  (error) in
        if let err = error 
            completionHandler(err)
        
        completionHandler(nil)
    

【问题讨论】:

您确定这是触发转场的唯一方法吗?回调没有被执行两次?从您在此处的代码看来,它应该可以按预期工作,这意味着问题很可能出在其他地方。最好的帮助可能是显示登录。 @DavidBerry 添加了。不确定这是否有帮助,或者您需要更多信息 @davidBerry 也是,是的,肯定它是唯一的 segue 触发器。如果我删除它,它会按预期工作 - 如果我将打印语句添加到 else 块,打印运行... 【参考方案1】:

无论哪种方式,您都在运行完成处理程序;如果你得到一个错误,你正在调用它,但是你会失败并以 nil 运行它。试试这个:

func login(username: String, password: String, completionHandler: @escaping (_ error: String?) -> ()) 
SessionHelper.shared.logUserIn(withUsername: username, andPassword: password)  (error) in
    if let err = error 
        completionHandler(err)
     else 
        completionHandler(nil)
    

【讨论】:

【参考方案2】:

您的login 函数在错误情况下调用completionHandler 两次。 if 属于以下声明。您应该将以下语句放在 else 块中,或者将 return 放在真正的块中。

【讨论】:

以上是关于从线程/ GCD/完成处理程序返回的主要内容,如果未能解决你的问题,请参考以下文章

说说GCD中的死锁

解析嵌套完成处理程序

完成处理程序 swift 3 从函数返回一个变量

如何从 NSURLSessionDataTask 完成处理程序返回 NSData

从 PromiseKit 中的完成处理程序返回 Promise

如何从NSURLSessionDataTask完成处理程序返回NSData