简体   繁体   中英

When Firebase function ends in Swift

I am using a Firebase in my app, it queries through a lot of users and gets the specific data that is needed, but when it starts querying - the rest of the function keep running too, instead of just querying so I can't understand when it ends.

For example in this code:

ref.observeEventType(.ChildAdded, withBlock: { snapshot in

            let user = snapshot.value!.objectForKey("User")
            let name = (user!["Name"])! as! String

            print("name")

            })
print("done")

Let's say we have 3 users in the Firebase Database - the printed code will be:

done
nameuser1
nameuser2
nameuser3

(or the done will be somewhere between the nameusers, depends on your internet connection - BUT it won't be the the last)

The Firebase callback block is asynchronous, while the print line is synchronous. This means that the block will run whenever it receives data back from its underlaying API calls, while the "print" (and other) lines which are outside the block will continue to be run seqeuentially.

This is why the print line is run before the callback block has been run.

You can use dispatch group, but only if you must, and you shouldn't do it on your main thread.

It's looks like this:

 let group = dispatch_group_create()
 dispatch_group_enter(group)

ref.observeEventType(.ChildAdded, withBlock: { snapshot in

            let user = snapshot.value!.objectForKey("User")
            let name = (user!["Name"])! as! String

            print("name")
            dispatch_group_leave(group)

            })

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
//will reach here only after group_leave  is called
print("done")

The "problem" your experiencing is due to the function observeEventType() being asynchronous. So it returns control to its caller before the values have actually been retrieved. Use an asynchronous callback like this and pass a function that will be called each time a value is retrieved from firebase...

updated for Swift 3

func getDataFromFirebase(callback: @escaping (_ user: String, _ name: String)->Void){
   ref.observeEvent(of: .childAdded, with:{(snapshot)-> Void in

        let user = snapshot.value!.objectForKey("User") as! String
        let name = (user!["Name"])! as! String

        callback(user, name)

   })
}

and call the function like this...

getDataFromFirebase(callback: {(user, name)-> Void in 
    print("got a user: \(user) and a name: \(name)")
})

This will print a user and a name for every child that is retrieved

let's start by analyzing your code :

  • firebase observe function is asynchronous
  • the print function is synchronous,

    result: it's impossible to force an asyc func to work as a sync.

It's just a wrong approach

Concerning how the compiler will compile your code :

first of all he will fire the observeEventType function and than he will pass to execute the other stuff (simply because it's async and needs time to finish the execution).

My advice for you to get this work the way you want is to prepare the whole of your needed data in viewDidLoad() function (put them in variables) and than just use these variables in your private functions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM