0

I am trying to fetch all the user names in my database but the nameArray only contains values while its inside that function, how can I fix this?

DataService.instance.getAllUserNamesPlease { (returnedNamesArray) in
            self.nameArray = returnedNamesArray
}

for userName in nameArray {
            if(userName.lowercased() == name!.lowercased()){

                self.userNameTaken = true
                self.progressView.progress = Float(progress / self.nameArray.count)
                progress += 1/self.nameArray.count
                break
                }
            }

nameArray is empty in this loop

func getAllUserNamesPlease(handler: @escaping (_ userNames: [String]) -> ()){

        REF_USERS.observeSingleEvent(of: .value) { (userNameSnapshot) in
            guard let userNameSnapshot = userNameSnapshot.children.allObjects as? [DataSnapshot] else {return}
            var namesArray = [String]()
            for names in userNameSnapshot {
                let name = names.childSnapshot(forPath: "userName").value as? String ?? "No Name"
                namesArray.append(name)
            }
            handler(namesArray)
        }
    }
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
tHatpart
  • 1,302
  • 3
  • 12
  • 27

1 Answers1

1

Any code that needs access to the results of an asynchronous call, should be inside that callback/completion handler. So your loop over nameArray, needs to be inside the {} braces:

DataService.instance.getAllUserNamesPlease { (returnedNamesArray) in
    self.nameArray = returnedNamesArray

    for userName in nameArray {
        if(userName.lowercased() == name!.lowercased()){

            self.userNameTaken = true
            self.progressView.progress = Float(progress / self.nameArray.count)
            progress += 1/self.nameArray.count
            break
            }
        }
    }
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • After a little debugging I found out that it does exist outside of the function, it needed some time to download the names. But I'm still dealing with a problem where it'll register a user when that username is already taken – tHatpart May 29 '19 at 00:15
  • It is indeed a timing issue, not a scope issue. But putting the code inside the completion handler, as my answer shows, solves the timing issue and is the correct solution. Also see https://stackoverflow.com/questions/37244952/how-can-i-access-firebase-variable-outside-firebase-function, https://stackoverflow.com/questions/39201596/when-firebase-function-ends-in-swift, https://stackoverflow.com/questions/30024795/swift-access-data-outside-closure – Frank van Puffelen May 29 '19 at 00:30