1

I'm trying to write a completion handler for a function that checks if a user is a member of a team in firebase.

I have a public class customFunctions in which I created a function ifUserIsMember. I seem to be a little stuck on the idea of completion handlers, and can't seem to figure out how to check the bool value on completion (if that makes sense). Here's my code for the class:

import Foundation
import GeoFire
import FirebaseDatabase


public class customFunctions {

func ifUserIsMember(userid: String, completionHandler: @escaping (Bool) -> ()) {
    let ref = FIRDatabase.database().reference()

    ref.child("teammembers").observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.hasChild(userid){
            completionHandler(true)
        }else{
            print("user is not a member of a team")
            completionHandler(false)
        }
    })
}
}

And here is where I'm calling it:

  @IBAction func signInButtonAction(_ sender: AnyObject) {
    //check if user is a member of a team
    let userid = self.uid

    checkFunctions.ifUserIsMember(userid: userid) { success in
        print("user is a member of a team")
        self.updateLocation(type: "in")
    }
}

It seems that it's returning true regardless of whether snapshot.hasChild(uerid) actually has that userid

adjuremods
  • 2,938
  • 2
  • 12
  • 17
Jake Ols
  • 2,792
  • 3
  • 18
  • 29
  • It doesn't sound like the issue is in the block, because you're calling it correctly. It seems the issue is in checking that the snapshot has that child. If you put in breakpoints are you always calling `completionHandler(true)`? – Guy Kogus Oct 19 '16 at 15:28
  • No, it seems that it first usually always returns false the first time the button is pressed (when the user is in fact a member of that team), but the second time it returns true. – Jake Ols Oct 19 '16 at 15:35
  • Actually nevermind - it's the other way around. It's still calling the self.updatelocation even when the user is not a member of the team – Jake Ols Oct 19 '16 at 15:38

3 Answers3

0

Try using :-

func ifUserIsMember(userid: String, completionHandler: @escaping ((_ exist : Bool) -> Void)) {
    let ref = FIRDatabase.database().reference()

    ref.child("teammembers/\(userid)").observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.exists(){
            completionHandler(true)
        }else{
            print("user is not a member of a team")
            completionHandler(false)
        }
    })
}
Dravidian
  • 9,945
  • 3
  • 34
  • 74
  • It says that function types cannot have argument label "exist" – Jake Ols Oct 19 '16 at 15:48
  • Still the same problem as before. Everything works fine, but for some reason it's still not working when the user is not a member. It first returns false, and then returns true directly after. – Jake Ols Oct 19 '16 at 15:55
  • Disable the button just after your first press :- `sender.isEnabled = false` and then in the if block again enable it – Dravidian Oct 19 '16 at 15:58
  • It's not on a double press. I added a breakpoint for when the completion handler returns true, and used a user account that should always return false. When I did this it first return "user is not a member" (the expected behavior), but then hit the breakpoint. So my best guess is for some reason it's not handling the if exists check correctly – Jake Ols Oct 19 '16 at 15:58
  • 1
    I'll mark your answer as accepted- as it lead me to my solution. Adding `@escaping ((_ exist : Bool) -> Void))` in ifUserIsMeber, and then changing my signInButtonAction to `checkFunctions.ifUserIsMember(userid: userid) { (exist) -> ()` in was the solution – Jake Ols Oct 19 '16 at 18:15
0

For anybody else that ran into this problem, this is what fixed it for me.

@IBAction func signInButtonAction(_ sender: AnyObject) {
    //check if user is a member of a team

    let userid = self.uid

    checkFunctions.ifUserIsMember(userid: userid) { (exist) -> () in
        if exist == true {
            print("user is a member of a team")
            self.updateLocation(type: "in")
        }
        else {
            print("user is not a member")
        }


    }


}



public class customFunctions {
let ref = FIRDatabase.database().reference()
func ifUserIsMember(userid: String, completionHandler: @escaping ((_ exist : Bool) -> Void)) {

    ref.child("teammembers").observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.hasChild(userid){
            completionHandler(true)

        }else{

            print("user is not a member of a team")
            completionHandler(false)
        }


    })

}

}

Jake Ols
  • 2,792
  • 3
  • 18
  • 29
0

Swift 3 & Firebase 3.17.0

This will do the trick, check for NSNull

func ifUserIsMember(userid: String, completionHandler: @escaping (Bool) -> ()) {
    let ref = FIRDatabase.database().reference()

    ref.child("teammembers").observeSingleEvent(of: .value, with: { (snapshot) in
        guard snapshot.value is NSNull else {
            print("\(snapshot) exists")
            completionHandler(true)
        }
        print("\(snapshot) is not exists")
        completionHandler(false)
    })
}