swift - 运行异步调用时在 MainQueue 上更新什么

标签 swift asynchronous firebase firebase-realtime-database grand-central-dispatch

我向 Firebase 发送了一些信息,如果成功,回调中可能会发生 5 件事,如果不成功,可能会发生 3 件事:

如果成功:

  1. 事件指示器已关闭

  2. 具有日期更新的类级别变量

  3. 出现一个警告,其中包含一条包含该变量的消息

  4. 推送到另一个vc

  5. sendButton 再次启用(一旦他们按下它就被禁用)

如果不成功:

  1. 事件指示器已关闭

  2. 出现一条警告消息,表明它不成功

  3. sendButton 再次启用(一旦他们按下它就被禁用)

当我尝试将 navigationController?.pushViewController 放在 mainQueue 上时,它总是有问题,特别是它并不总是执行。

//caused problems
DispatchQueue.main.async {
         navigationController?.pushViewController(nextVC, animated: false)
            }

一旦我将其取下并将其留在后台,它就可以正常运行。我知道我应该更新警报,但是警报使用的类级别变量和关闭事件指示器呢?

Firebase 代码:

@IBOutlet weak fileprivate var sendButton: UIButton!

let date = Date() //formatted in viewDidLoad
var todaysDate = ""
let activityIndicator = UIActivityIndicatorView() //formatted in viewDidLoad

@IBAction fileprivate func sendButtonTapped(_ sender: UIButton){

sendButton.isEnabled = false
view.addSubview(activityIndicator)

//dict has some values

nextVCRef?.updateChildValues(dict, withCompletionBlock: {
            (error, ref) in

            if error != nil{

              DispatchQueue.main.async {
                self.activityIndicator.removeFromSuperView
                self.alertError()
                self.sendButton.isEnabled = true//i normally would put this is the alertError action but for clarity i put it here
              }
              return
            }

            DispatchQueue.main.async {
                self.todaysDate = self.date
                self.alertSuccessful()//everything happens in the function
            }
        })
}

fileprivate alertSuccessful(){
        self.activityIndicator!.removeFromSuperView
        let alert = UIAlertController(title: "Thank You!", message: "Today's date is \(self.todaysDate).", preferredStyle: UIAlertControllerStyle.alert)
        let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default){
            (action) in
            self.sendButton.isEnabled = true
            _ = self.navigationController?.pushViewController(nextVC, animated: false)
        }
        alert.addAction(action)
        present(alert, animated: true, completion: nil)
}

fileprivate alertError(){
        let alert = UIAlertController(title: "Unknown Error!", message: "There was an error. Try again.", preferredStyle: UIAlertControllerStyle.alert)
        let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
        alert.addAction(action)
        present(alert, animated: true, completion: nil)
    }
}

问题是在设置变量、关闭事件指示器、出现警报、重新启用 sendButton 和执行推送之间,应该不应该 在主队列中?

顺便说一句,我不需要在后台更新日期变量,但在另一种情况下,我可能会从 Firebase 中提取一些信息,并且该变量将在回调中更新。我没有包含该代码而是使用了它,因为要点是类变量是否应该在后台线程的主队列上更新?

最佳答案

正如@shallowThought 在答案下方的评论中指出的那样,任何具有 UI 前缀的内容,如 UINavigationControllerUIViewUIActivityIndi​​catorUIButton 都是 user interface 对象,应该在 mainQueue 上。 mainQueue 专门用于用户界面对象或缩写UI 对象。多亏了他,一些东西很容易记住 :) 变量也应该更新。

@Paulo Mattos 在评论中指出,我不知道 Firebase 的美妙之处在于,Firebase 完成 block 全部发生在 mainQueue 上,因此它减轻了必须添加 DispatchQueue.main.asyc 的麻烦{} p>

为他们的评论点赞!

关于swift - 运行异步调用时在 MainQueue 上更新什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44165601/

相关文章:

iphone - 有没有办法阻止模态视图在 iPhone 上全屏显示

java - AsyncTask - onPostExecute UI 混淆

c# - 在 C# 中从非异步调用异步代码的最佳方式是什么(即发即弃)

ruby - 与 EventMachine 一起 sleep

javascript - 如何在 firebase 云函数中使用 javascript setTimeout 函数

运行时快速字符串插值

swift - 将节点的 Sprite 更改为动画 (spriteKit)

ios - Swift AVCaptureMovieFileOutput 找不到 URL

android - 将 firebase analytic 链接到 Google play

javascript - 如何修复错误窗口未定义