Reputation: 115
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
Reputation: 457
Another way is to create a delegate protocol and call it inside the closure
Upvotes: 0
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
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
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.
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