我向 Firebase 发送了一些信息,如果成功,回调中可能会发生 5 件事,如果不成功,可能会发生 3 件事:
如果成功:
事件指示器已关闭
具有日期更新的类级别变量
出现一个警告,其中包含一条包含该变量的消息
推送到另一个vc
sendButton 再次启用(一旦他们按下它就被禁用)
如果不成功:
事件指示器已关闭
出现一条警告消息,表明它不成功
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
前缀的内容,如 UINavigationController
或 UIView
或 UIActivityIndicator
或 UIButton
都是 user interface
对象,应该在 mainQueue 上。 mainQueue 专门用于用户界面对象或缩写UI
对象。多亏了他,一些东西很容易记住 :) 变量也应该更新。
@Paulo Mattos 在评论中指出,我不知道 Firebase 的美妙之处在于,Firebase 完成 block 全部发生在 mainQueue 上,因此它减轻了必须添加 DispatchQueue.main.asyc 的麻烦{} p>
为他们的评论点赞!
关于swift - 运行异步调用时在 MainQueue 上更新什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44165601/