0

I'm very new to SwiftUI so bare with me - it's for a project.

I have stored user's details into my Firestore database which looks like this:

image of database

I want to take the name from the database and display it in a Text("Hello" [name]) I have been able to fetch the name from the database and append it into an array. This function is run when the 'Log in' button is clicked.

The code is as follows:

func getData(){
let docRef = db.collection(FStore.collectionName).document(userID)

docRef.getDocument { (document, error) in
    if let document = document, document.exists {
        if let fetchedName = document.get("name") as? String {
            userArray.append(fetchedName)
            print(userArray)
        }
    }
}

}

When printing userArray, the correct name does print. However I am struggling to display the name outside of the console and on my Text UI field. When I attempt the code below, it gives me an index out of range error.

Text("Hello: \(userArray[0])")

Any help is appreciated / any other methods of retrieving field data from a specific document.

  • `getDocument()` is asynchronous I'd assume, while you're immediately trying to use the array before it finishes – Steve M Jan 27 '22 at 14:56
  • That's what I thought too. I call the getData() function when the Login button is clicked and then display the next view using a NavigationLink but it still isn't working. – Peter Reid Jan 27 '22 at 14:59

1 Answers1

0

Thanks to @Steve M , it ended up being a kind of silly mistake.

He was right, the display was attempting to read the array before the array had even been populated.

As described in my comments, I called the getData() function then ran code to display the next screen. I wrapped the "display next screen code" in a DispatchQueue to delay the next screen being displayed

DispatchQueue.main.asyncAfter(deadline@ .now() + 1){
nextView = true
}

This ran a 1-second delay before displaying the next screen and successfully displayed the name from the database.

  • This is a very fragile approach — if your network request takes more than 1 second, it will fail. Instead, you could consider checking the length of the array before accessing an elect on it. – jnpdx Jan 27 '22 at 18:00
  • 1
    Oh gosh, please don't do this. It will easily break and you'll have all kinds of wonky issues. Firebase is asynchronous and data from firebase is only valid within the closure following the function call. See [this answer](https://stackoverflow.com/questions/56442492/searchbar-problem-while-trying-to-search-firestore-and-reload-the-tableview/56446914#56446914) and perhaps you should consider a completion handler as shown in [this answer](https://stackoverflow.com/questions/61091335/using-firestore-db-how-can-i-break-out-of-a-for-loop-inside-of-a-snapshot-liste/61104977#61104977) – Jay Jan 27 '22 at 20:36