0

I have an odd issue and I’m not sure what I am doing wrong.

I have the following function that I want called in viewDidLoad to load all documents in a collection from Firestore that will be displayed in a tableview.

func functionName() -> [String] {

    var NameArray = [String]()

    db.collection("Names").getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                NameArray.append("\(document.documentID)")
            }
        }
    }
    print(NameArray)
    print(NameArray.count)

    return (NameArray)
}

The function throws a warning result is being ignored. I don’t want to silence it as I need the value, it should return an array with the document names.

When I tried the below code, it returns the array and count as expected.

@IBAction func fetchUsersButton(_ sender: UIButton) {
    var NameArray = [String]()

    db.collection("Names").getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                NameArray.append("\(document.documentID)")
            }
        }
        print(NameArray)
        print(NameArray.count)
    }
}

However, I need to be able to return the array created so it can be used outside the function. Is anyone able to help?

0

2 Answers 2

5

Instead of returning an array you need to place it in a completion handler.

func functionName(_ completion: @escaping ([String]) -> Void) {

    var NameArray = [String]()

    db.collection("Names").getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                NameArray.append("\(document.documentID)")
            }
        }

        completion(NameArray)
    }        
}
Sign up to request clarification or add additional context in comments.

Comments

1

The reason that you aren't returning anything is because db.collection().getDocuments is an asynchronous function. What this means is that the function gets to "return" before the db.collection().getDocuments code is done executing.

"Return" assumes that the code will execute synchronously which means it will execute line by line in a predictable order. An asynchronous function is one in which we don't know when it will finish executing (which is always true of network code).

What if the network is down? What if it takes a long time to download? Since we can't know, we use a completion handler to "return" what we need once the function has completed. The other suggestions are great, below is another solution. As a note, it assumes that this function is part of class, and you want to assign the result to an outside variable.

class MyClass {

      var myNameArray = [String]()

      func functionName() {

          db.collection("Names").getDocuments() { (querySnapshot, err) in
              if let err = err {
                  print("Error getting documents: \(err)")
              } else {
                  for document in querySnapshot!.documents {
                      myNameArray.append("\(document.documentID)")
                  }
              }
          }
      }

}

Another small thing about naming conventions, variables should utilize camelCase, so nameArray is preferable to NameArray.

Comments

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.