1

I am trying generate a unique 8 digit userID as a key to my user in my Firebase database vs. the 28 digit one created in Firebase.

In the function I want to generate the random variable and then check it against the database to see if it exists. If it exists in the database I want to call the recursively until a unique key is created.

I tried

func createUniqueID() -> String {

    let userID = generateUserID()

    let ref = Database.database().reference(withPath: "users")
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.hasChild(userID) {
            return createUniqueID() //errors here
        }
        else {
            return userID //errors here
        }
    })
}

but I get errors on both return lines in the firebase closure "Unexpected non-void return value in void function"

I tried doing it as an inline function

func wtf() -> String {

    let userID = "123456"//generateUserID()

    func doesUserIDExistAlready(userID: String, complete: @escaping(String) -> ()) {

        let ref = Database.database().reference(withPath: "users")
        ref.observeSingleEvent(of: .value, with: { (snapshot) in
            if snapshot.hasChild(userID) {
                complete( self.wtf() )
            }
            else {
                complete( userID )
            }
        })
    }

    doesUserIDExistAlready(userID: userID) { userID in
        return userID //warning here
    }
}

but I get a warning that "Expression of type 'String' is unused" on return userID

I also tried using an inline function without a completion but returning a string

func wtf2() -> String {

    let userID = "123456"//generateUserID()

    func doesUserIDExistAlready(userID: String) -> String {

        let ref = Database.database().reference(withPath: "users")
        ref.observeSingleEvent(of: .value, with: { (snapshot) in
            if snapshot.hasChild(userID) {
                return self.wtf2() //errors here
            }
            else {
                return userID //errors here
            }
        })
    }

    return doesUserIDExistAlready(userID: userID)
}

but I also get errors on both return lines in the firebase closure "Unexpected non-void return value in void function"

is this possible to do?

Ron Myschuk
  • 6,011
  • 2
  • 20
  • 32
  • Related, but not a duplicate IMO: https://stackoverflow.com/questions/27390656/how-to-return-value-from-alamofire – Sweeper Apr 08 '20 at 17:41

1 Answers1

2

Asking Firebase for data is an asynchronous operation, so createUniqueID can't return a String immediately. You can accept a completion closure to "return" the ID to the caller (just like how observeSingleEvent uses a closure to give you the value).

func createUniqueID(_ completion: (String) -> Void) {

    let userID = generateUserID()

    let ref = Database.database().reference(withPath: "users")
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.hasChild(userID) {
            createUniqueID(completion)
        }
        else {
            completion(userID)
        }
    })
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • brilliant, I hadn't thought of completing it from the firebase call vs trying to return a value from a recursive func. Thanks – Ron Myschuk Apr 08 '20 at 17:39