Getting Data Out of a Closure That Retrieves Data from Firebase

getting data out of a closure that retrieves data from firebase

That's because when you fetch data from Firebase the call is Asynchronous. What you can do:

Option 1 - Set your logic inside the closure (Like what you have that print the var inside the closure).

Option 2 - Define your own closure that going to receive your data like:

func myMethod(success:([String])->Void){

ref?.observeEventType(.Value, withBlock: { snapshot in
var newNames: [String] = []
for item in snapshot.children {
if let item = item as? FIRDataSnapshot {
let postDict = item.value as! [String: String]
newNames.append(postDict["name"]!)
}
}
success(newNames)
})
}

Option 3 - Use the delegate pattern

protocol MyDelegate{
func didFetchData(data:[String])
}

class MyController : UIViewController, MyDelegate{

func myMethod(success:([String])->Void){
ref?.observeEventType(.Value, withBlock: { snapshot in
var newNames: [String] = []
for item in snapshot.children {
if let item = item as? FIRDataSnapshot {
let postDict = item.value as! [String: String]
newNames.append(postDict["name"]!)
}
}
self.didFetchData(newNames)
})
}

func didFetchData(data:[String]){
//Do what you want
}

}

Retrieve String value from function with closure in Swift

You need to create completion handler like this

func GetUsername(uid:String , completion: (String) -> ()) {
firebase.child("Users").child(uid).observeSingleEventOfType(.Value) { (snapshot:FIRDataSnapshot) in
if let username = snapshot.value!["Username"] as? String
completion(username)
}
else {
completion("")
}
}

And call function like this way

self.GetUsername(str) { (name) -> () in
if name.characters.count > 0 {
print(name)
}
else {
print("Not found")
}
}

Retrieve value from function with swift closure

If I'm understanding the structure/question correctly, your goal is to access the WholeDocument array in another SwiftUI view. The way to do that could be:

class UserData : ObservableObject {

// Use Firebase library to configure APIs
private var db = Firestore.firestore()

@Published var WholeDocument : Array = []

init() {
db.collection("Users").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
completion([""])
} else {
for document in querySnapshot!.documents {
// print("\(document.documentID) => \(document.data())")
self.WholeDocument.append(document.documentID)
}
}
}
}
}

struct MyContentView : View {

@ObservedObject var database: UserData

var body: some View {
// access database.WholeDocument
List(database.WholeDocument, id: \.self) {
// do something
}
}

That way, when you initialize MyContentView with an instance of UserData, you will be able to observe WholeDocument in that view.

retrieve data from firebase failed

Due to asynchronous operations, there is no value (yet) at your third print statement.

Your first two print statement actually execute after your third print statement even if it doesn't look like it. If you create breakpoints at each print statement, you will be able to see the order of execution.

So to guarantee the data is back from Firebase, you should only be calling the data inside here:

databaseRef?.child("userTable").child(email).observe(.value, with: { (snapshot) in
// Manipulate data here
}

If you prefer the calls to be synchronous, you can do the following:

    func retrieveData(user: User) {
//let userID = Auth.auth().currentUser?.uid
let email = user.emailAddress!
// print(email)
databaseRef?.child("userTable").child(email).observe(.value, with: { (snapshot) in
// Get user value
print("whats up ")
if let value = snapshot.value as? [String:String] {
let res = value["posts"]
user.deserialize(data: res!)
if( user === self.u1) {
print("they are same obj") // this will print, so they are pointing to the same address
}
print(self.u1.posts) // this also printed the things I want
}
// ...
})
if( user === self.u1) {
print("they are same obj outside") // this also prints
}
DispatchQueue.main.async{
print(self.u1.posts) // Now called sequentially
}
}

How do I make it such that .observe in Firebase retrieves all its data before calling reload collection view

Try :-

If you are calling for .value as FIRDataEventType only then its possible for you to check the count

let count = snapshot.childrenCount
if self.URLArrayStringRecents.count == Int(count){
self.whatsNewCollectionView.reloadData()
}

Otherwise if you are calling for .childAdded as FIRDataEventType, it will return single snapshot at a time , you can either fix up a NSTimer which waits for a certain time period after calling a .reloadData().

Firebase Observe Closure Not Called

A .childAdded event is fired for each child node that exist initially, or that is added later. If there are child nodes, .childAdded is not fired.

If you want to know whether data exists, you should observe the .value event.

If you observe both .child... and .value on the same reference/query, Firebase will only retrieve the data once. So there is no extra data transfer to observe both events.

Also see:

  • How do I check if a firebase database value exists?
  • Checking if Firebase snapshot is equal to nil in Swift


Related Topics



Leave a reply



Submit