当我将数据发送到 Firebase
时,有时必须使用嵌套完成 block
将数据
发送到不同的节点
。
实际代码如下,但这里有一个示例
buttonPressed{
activityIndicator.startAnimating()
levelTwoRef //send levelTwo data run 1st callback
scoreRef //send score data run 2nd callback
powerRef //send power data run 3rd callback
lifeRef //send life data run Last callback for dispatch_async...
dispatch_async(dispatch_get_main_queue()){
activityIndicator.stopAnimating()
performSegueWithIdentifier....
}
按下按钮后,我会显示一个activityIndicator
。大多数时候一切正常,但我看到在 scoreRef
和 PowerRef
周围的调用失败,这将是第一个和第二个回调
。问题是我不会删除 activityIndicator
直到最后一个 completion block
运行,因此 activityIndicator
无限期地旋转(它永远不会到达那里) 。当旋转器旋转时,我还会阻止该 View 的用户界面,因此用户无能为力。
一些人建议我在通话中放置一个计时器
,如果在 X 时间范围内没有完成,我会显示一个取消按钮来停止操作。 我不知道如何添加计时器。对于取消按钮,我只需使用 alertController
来停止一切
我有 2 个问题:
- 如何向调用添加
计时器
以及在什么时候使用它?我这么说是因为有时它会完成,有时它会完成 在不同的 block 上失败。 - 我如何确定所有事情应该完成的时间?我这么说是因为它通常需要几秒钟 成功完成,但有时需要长达 45 秒的时间。 如果网络拥塞,调用可能不会失败,只是 等待。
我仍在使用 Swift 2.2,因为我引用的书籍都是用它编写的。
代码:
class LevelOneCompletedController: UIViewController{
@IBOutlet weak var completedLevelButton: UIButton!
var ref: FIRDatabaseReference!
let uid = FIRAuth.auth()?.currentUser?.uid
let activityIndicator = UIActivityIndicatorView()
var levelDict = [String:AnyObject]()
var scoreDict = [String:AnyObject]()
var powerDict = [String:AnyObject]()
var lifeDict = [String:AnyObject]()
override func viewDidLoad() {
super.viewDidLoad()
self.ref = FIRDatabase.database().reference().child(self.uid!)
}
@IBAction func completedLevelButtonTapped(sender: UIButton){
self.completedLevelButton.enabled = false
self.activityIndicator.center = self.view.center
self.activityIndicator.hidesWhenStopped = true
self.activityIndicator.activityIndicatorViewStyle = .WhiteLarge
self.view.addSubview(self.activityIndicator)
self.activityIndicator.startAnimating()
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
self.boardPassed()
}
fun boardPassed(){
let levelTwoRef = self.ref.child("levelTwo").childByAutoID()
levelTwoRef?.updateChildValues(self.levelDict, withCompletionBlock: {
(error, ref) in
if error != nil{....}
let scoreRef = self.ref.child("Score").childByAutoID()
scoreRef?updateChildValues(self.scoreDict, withCompletionBlock: {
(error, ref) in
if error != nil{....}
let powerRef = self.ref.child("Power").childByAutoID()
powerRef?updateChildValues(self.powerDict, withCompletionBlock: {
(error, ref) in
if error != nil{....}
let lifeRef = self.ref.child("Life").childByAutoID()
lifeRef?updateChildValues(self.lifeDict, withCompletionBlock: {
(error, ref) in
if error != nil{....}
dispatch_async(dispatch_get_main_queue()){
self.activityIndicator.stopAnimating()
self.performSegueWithIdentifier("levelTwoSeque", sender: self)
self.completedLevelButton.enabled = true
UIApplication.sharedApplication().endIgnoringInteractionEvents()
}
}
}
}
}
}
}
最佳答案
没有计时器的解决方案是跟踪连接状态。您可以通过以下方式监听状态:
let connectedRef = FIRDatabase.database().reference(withPath: ".info/connected")
connectedRef.observe(.value, with: { snapshot in
if snapshot.value as? Bool ?? false {
print("Connected")
} else {
print("Not connected")
}
})
您可以将更新的状态保存在变量中,并在每次请求之前检查它,然后根据需要启动/停止 activityIndicator
。
更多信息可以在这里找到:Detecting Connection State .
关于ios - Swift iOS - 如果对 Firebase 的网络调用时间过长,如何使用计时器关闭事件指示器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42869068/