Ron Myschuk
Ron Myschuk

Reputation: 6071

Recursive func with closure inside

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?

Upvotes: 1

Views: 66

Answers (1)

Sweeper
Sweeper

Reputation: 274413

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)
        }
    })
}

Upvotes: 2

Related Questions