运行 异步调用时在 MainQueue 上更新什么
What to Update on MainQueue while running Async Call
我向 Firebase 发送了一些信息,如果成功,回调中可能会发生 5 件事,如果不成功,可能会发生 3 件事:
如果成功:
activity 指标被关闭
一个 class 级别变量与日期更新
出现一条警告,其中包含一条包含该变量的消息
向另一个执行推送vc
sendButton 再次启用(按下后禁用)
如果不成功:
activity 指标被关闭
出现一条警告消息,表明它不成功
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
的内容,如 UINavigationController
或 UIView
或 UIActivityIndicator
或 [=14] =] 都是 user interface
个对象,应该在 mainQueue 上。 mainQueue 专门用于用户界面对象或缩写UI
对象。多亏了他,一些东西很容易记住 :) 变量也应该更新。
@Paulo Mattos 在评论中指出,我不知道 Firebase 的美妙之处在于 Firebase 完成块都发生在 mainQueue 上,因此它减轻了必须添加的麻烦 DispatchQueue.main.asyc{}
为他们的评论点赞!
我向 Firebase 发送了一些信息,如果成功,回调中可能会发生 5 件事,如果不成功,可能会发生 3 件事:
如果成功:
activity 指标被关闭
一个 class 级别变量与日期更新
出现一条警告,其中包含一条包含该变量的消息
向另一个执行推送vc
sendButton 再次启用(按下后禁用)
如果不成功:
activity 指标被关闭
出现一条警告消息,表明它不成功
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
的内容,如 UINavigationController
或 UIView
或 UIActivityIndicator
或 [=14] =] 都是 user interface
个对象,应该在 mainQueue 上。 mainQueue 专门用于用户界面对象或缩写UI
对象。多亏了他,一些东西很容易记住 :) 变量也应该更新。
@Paulo Mattos 在评论中指出,我不知道 Firebase 的美妙之处在于 Firebase 完成块都发生在 mainQueue 上,因此它减轻了必须添加的麻烦 DispatchQueue.main.asyc{}
为他们的评论点赞!