Jared Davidson
Jared Davidson

Reputation: 115

Return value for function in nested function (Swift 3 | Xcode)

I'm trying to return a value for a function from inside of a nested function. I understand why it doesn't work, but I just need to know a workaround for my type of problem.

In my code, I'm checking whether or not a person has already been created inside of my Firebase Database. So inside of the usersRef function, you'll see that if the value return from firebase is "nil" then the user hasn't been created and vice versa.

When I say : return userBool it's giving me this error:

Unexpected non-void return value in void function

Been looking for a clean workaround, but the only thing I can think of is having to create this function over and over again for each of the various times I want to check it. Obviously, I'd rather not do that, haha, so if you could help me out by giving some suggestions on how to fix this and have a clean solution, let me know! :)

func checkIfUserExists(userID : String) -> Bool {
    var userBool = Bool()
    var usersRef = FIRDatabase.database().reference()
    usersRef.child("users").child(userID).observeSingleEvent(of: .value, with: {
    snapshot in
        if snapshot.value != nil {
            userBool = true
            return userBool
        }
        else {
            userBool = false
            return userBool
        }
    })
}

UPDATE :

Thanks to your suggestions, I added a completion, and it worked perfectly. :)

func checkIfUserExists(userID : String, completion: @escaping (_ success: Bool) -> ()){
    var userBool = Bool()
    var usersRef = FIRDatabase.database().reference()
    usersRef.child("users").child(userID).observeSingleEvent(of: .value, with:{
        snapshot in
            if snapshot.value != nil {
                print("userBool!", userBool)
                userBool = true
            }
            else {
                print("userBool2!", userBool)
                userBool = false
            }
        completion(userBool)
    })
}

Upvotes: 2

Views: 3029

Answers (4)

Carolina
Carolina

Reputation: 457

Another way is to create a delegate protocol and call it inside the closure

Upvotes: 0

Artem Stepanenko
Artem Stepanenko

Reputation: 3501

The only way to make it return what you want is possible if the observeSingleEvent(...) function executes the closure synchronously to its call.

If it's true, you can try the following:

func checkIfUserExists(userID : String) -> Bool {
    var userBool = false
    var usersRef = FIRDatabase.database().reference()
    usersRef.child("users").child(userID).observeSingleEvent(of: .value, with: {
        userBool = $0.value != nil
    })
    return userBool
}

If the closure of observeSingleEvent(...) is called after a while, return a result of your method in a closure as Moritz suggested, not as a return value.

Upvotes: 1

Moritz Lang
Moritz Lang

Reputation: 36

There is no way to return from the outer function from within the inner one. The only way I can think of is by using a completion handler, that you can then call from within the nested function like so:

func checkIfUserExists(userID : String, completion: @escaping (_ userExists: Bool) -> Void)

Upvotes: 2

JDM
JDM

Reputation: 893

The problem is you're in a closure, that doesn't expect a return type.. How are you call this function?

Some ideas: * Pass a closure to this function, which then gets called, instead of trying to return.

  • Keep a mapping of the results somewhere, update that from the closure and always check against that mapping.

Also, it looks like instead of

if snapshot.value != nil {
        userBool = true
        return userBool
    }
    else {
        userBool = false
        return userBool
    }

You could just do this:

guard snapshot = snapshot else { return }
return snapshot.value

Upvotes: 1

Related Questions