Swift iOS - 如果对Firebase的网络调用需要很长时间,如何使用计时器关闭活动指示器



当我向Firebase发送数据时,有时我必须使用nested completion blocksdata发送到不同的nodes

实际代码如下,但这是一个示例

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。大多数时候一切正常,但我看到呼叫在scoreRefPowerRef附近失败,这将是第 1 次和第 2 次callback。问题是我不会删除activityIndicator,直到最后一个completion block运行,所以activityIndicator无限期地旋转(它永远不会到达那里)。我还在微调器旋转时阻止了该视图的用户界面,因此用户无法执行太多操作。

有些人建议我在通话中放一个timer,如果它没有在 X 时间范围内完成,我会提供一个取消按钮来停止操作。我不知道如何添加计时器。对于取消按钮,我只会使用alertController来停止所有内容

我有两个问题:

  1. 如何向呼叫添加timer,在何时使用它?我这么说是因为有时它完成其他时候它 在不同的块上失败。
  2. 如何确定所有内容应该完成的时间量?我说是因为通常需要几秒钟 成功完成,但其他时候最多需要 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

可在此处找到详细信息:检测连接状态。

最新更新