当我向Firebase
发送数据时,有时我必须使用nested completion blocks
将data
发送到不同的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
。大多数时候一切正常,但我看到呼叫在scoreRef
和PowerRef
附近失败,这将是第 1 次和第 2 次callback
。问题是我不会删除activityIndicator
,直到最后一个completion block
运行,所以activityIndicator
无限期地旋转(它永远不会到达那里)。我还在微调器旋转时阻止了该视图的用户界面,因此用户无法执行太多操作。
有些人建议我在通话中放一个timer
,如果它没有在 X 时间范围内完成,我会提供一个取消按钮来停止操作。我不知道如何添加计时器。对于取消按钮,我只会使用alertController
来停止所有内容
我有两个问题:
- 如何向呼叫添加
timer
,在何时使用它?我这么说是因为有时它完成其他时候它 在不同的块上失败。 - 如何确定所有内容应该完成的时间量?我说是因为通常需要几秒钟 成功完成,但其他时候最多需要 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
。
可在此处找到详细信息:检测连接状态。