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

What to Update on MainQueue while running Async Call

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

如果成功:

  1. activity 指标被关闭

  2. 一个 class 级别变量与日期更新

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

  4. 向另一个执行推送vc

  5. sendButton 再次启用(按下后禁用)

如果不成功:

  1. activity 指标被关闭

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

  3. sendButton 再次启用(按下后禁用)

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

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

一旦我将其取下并将其留在后台,它 运行 非常好。我知道我应该更新警报,但是警报使用的 class 级别变量和关闭 activity 指标呢?

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

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

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

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

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

为他们的评论点赞!