【问题标题】:GCD Not Executing In Block OrderGCD 未按块顺序执行
【发布时间】:2016-08-09 21:43:49
【问题描述】:

我正在尝试从我的 Firebase 数据库中检查某些节点是否存在,如果不存在,请在数据库中创建新节点。我需要我的方法loadAll() 在它调用创建任何缺失节点autoCheck 的第二种方法之前完全执行。我尝试了一个调度组来执行此操作,但它不起作用,print("Done downloading!") 在完成检查数据库之前被调用。谢谢!!

代码:

func loadAll(){
    var deleted_load = false
    var poor_load = false
    var allLoadDone = false

    if let user = FIRAuth.auth()?.currentUser {
        let uid = user.uid

        let refff = FIRDatabase.database().reference()
        let userRef = refff.childByAppendingPath("users/\(uid)")


        //When making new fields increase this var
        var howmany = 2
        var done = 0

        var downloadGroup = dispatch_group_create()
        dispatch_group_enter(downloadGroup)
        userRef.queryOrderedByValue().observeEventType(.ChildAdded, withBlock: { snapshot in
            allLoadDone = true
            if(!snapshot.exists()){
                print("ERR DOES NOT EXCIST")
                self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 1)
                return
            }
            if let score = snapshot.value as? Int {
                if(snapshot.key=="deleted"){
                    deleted_load = true
                }
                if(snapshot.key=="Staff_Poor"){
                    poor_load = true
                }
                print("\(snapshot.key) is \(score)")
                self.counter.text = String(score)
            }
            done = done + 1
            if(done>=(howmany)){
                self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 2)
            }
        })
            dispatch_group_leave(downloadGroup)

        dispatch_group_notify(downloadGroup, dispatch_get_main_queue()) { // 2
            print("Done downloading!")
        }
    } else {
        print("No user!")
        gotoLogin()
    }
}

func autoCheck(deleted_load: Bool, poor_load: Bool, userRef: FIRDatabaseReference, ig: Int) -> Bool{
    print("ID IS: \(ig)")
    var newUserData = ["deleted": 0, "Staff_Poor": 0]
    print("deleted_load: \(deleted_load)")
    if deleted_load==true{
        newUserData.removeValueForKey("deleted")
    }
    print("poor_load: \(poor_load)")
    if poor_load==true{
        newUserData.removeValueForKey("Staff_Poor")
    }
    if(!newUserData.isEmpty){
        userRef.updateChildValues(newUserData)
    }

    return true
}

【问题讨论】:

    标签: swift firebase grand-central-dispatch firebase-realtime-database


    【解决方案1】:

    您对dispatch_group_leave(downloadGroup) 的调用必须放在完成处理程序闭包中。现在,你有它在外面,这意味着组将在异步调用完成之前完成。

    但让我们退后一步,了解调度组的目的。典型的模式是在您执行一系列异步任务时使用调度组,并且您想知道它们何时全部完成。因此,对于每个任务,您在调用某个异步进程之前进入组,然后将该组留在该异步进程的完成处理程序中,类似于:

    let group = dispatch_group_create()
    
    for object in arrayOfObjects {
        dispatch_group_enter(group)
        performSomeAsynchronousActionWithObject(object) { result in 
            // do something with `result`
            ...
            dispatch_group_leave(group)
        }
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue()) {
        print("done performing asynchronous task with all of those objects")
    }
    

    坦率地说,在这里使用调度组可能不合适。每个“进入”都与相应的“离开”匹配的调度组的概念。您调用了一次“进入”,但不清楚您是否有任何保证观察者最终会被调用多少次。

    但在这种情况下,您正在处理一个“观察者”,即无论事件发生多少次都会调用的一些代码块。它可能根本不会发生。它可能会发生很多次。这只是观察到的事件发生了多少次的问题。

    现在,如果您确定这将被调用一次且仅一次,那么从技术上讲,这种模式是可行的。但如果它只被调用一次,你就根本不需要调度组。

    【讨论】:

    • 嘿,我还有一个问题,由于某种原因,如果用户不在我的数据库中,(例如,如果它是新用户)userRef.queryOrderedByValue().observeEventType(.ChildAdded, withBlock: { snapshot in 不会执行。我做错了什么还是 Firebase 的工作原理?
    • 我不是 Firebase 方面的专家,但使用观察者模式,无论触发 .ChildAdded 事件多少次,通常都会调用该闭包。您能保证触发该事件的次数吗?
    • .ChildAdded 事件被触发一次。我运行该应用程序两次,一次是在我的数据库中存在users/<user_uid>,一次是从我的数据库中删除users/<user_uid>。在users/<user_uid> 存在的情况下,.ChildAdded 事件被触发,但第二次未能触发。 @Rob
    • 如果我在关注你,有时会调用观察者,有时则不会。那么调度组模式可能没有意义。仅当您知道每个“输入”都将与一个(不是零,不是多个)“叶子”匹配时才有意义。
    • 没错。但是,我希望每次都触发事件,为什么当我从数据库中删除 users/<user_uid> 时它不触发? @Rob
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 2020-06-11
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多