0

I'm trying to Grab all Fields as dictionary from 1 document. But when I try to do it i just get returned with empty array. I tried getting help from documentation and it's not working.

tho this line of code shows it not empty

print("Cached document data: (dataDescription)")

var user:String = (Auth.auth().currentUser?.email)! // I used email as name of document.

var Groups = [String:Any]()

    let docRef = AppDelegate.db.collection("JoinedGroups").document(user)

    docRef.getDocument(source: .cache) { (document, error) in
        if let document = document {
            let dataDescription = document.data()
            self.Groups = dataDescription!   // unwrapping here
            print("Cached document data: \(dataDescription)")
        } else {
            print("Document does not exist in cache")
        }
    }
    // Do any additional setup after loading the view.
    print(Groups)

}

Here are my results: document.data() is shown as dictionary when i hoover over definition

[:] //Shown as empty??

Cached document data: Optional(["test new": test new, "g3": g3, "g1": g1])

Thank You very much if i can get some help on this issue.

1
  • FYI you can edit your question using the edit link instead of adding new information in a comment. Commented May 24, 2019 at 16:19

1 Answer 1

1

The main issue here is that FireStore is asynchronous. It takes time for Firestore to return data from the internet and that data is only valid inside the closure following the getDocument.

That means the print(Groups) function will execute before the code inside the closure, so it's empty. Moving the print inside the closure will work.

var Groups = [String:Any]()
    let docRef = AppDelegate.db.collection("JoinedGroups").document(user)
    docRef.getDocument(source: .cache) { (document, error) in
        if let document = document {
            let dataDescription = document.data()
            self.Groups = dataDescription!   // unwrapping here
            print("Cached document data: \(dataDescription)")
        } else {
            print("Document does not exist in cache")
        }
        print(self.Groups)
    } 
}

May I also suggest you stick with naming conventions where vars are lowercases, e.g. groups instead of Groups. Upper case are usually for class definitions UserClass or GroupClass.

One last thing... documentID's (their 'key') cannot be changed. What that means is if your structure is this

JoinedGroups
   [email protected]
      name: "Jimmy"
      fav_food: "Pizza"

and you reference that user throughout your app, when they decide to change their email provider, you'll have to go through everywhere in your strucutre, read in that node, delete the node and write it back out with the updated email. How you fix it is it disassociate the documentID (key) from the data it contains

JoinedGroups
   users_uid
      name: "Jimmy"
      fav_food: "Pizza"

as uid's never change, the email can change 20 times and not affect your app.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much. I appreciate your help. I will take into account , what you mentioned.
I got question , If data is only valid within closure of getDocument. How can i get the data out? I want values from field. Is there another way.
@Kenny There are a number of options but the key is to let the closure control the flow of the app. In other words, don't try to populate a tableView dataSource outside of the closure, populate it within the closure when the data is valid. A tableView dataSource is often a class var anyway, so that model works well. There are a lot of examples here on SO about that flow with Firestore - perhaps you can find one that matches your use case and if not, ask another question, and we'll take a look!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.