0

I created a login mechanism with phone number. I want to check if the phone number is already registered or not, but the function I created will always return false. How to make it wait until the task is finished and then return?

func isPhoneNumberRegistered(phoneNumber: String) -> Bool {
    var isRegistered = false
    
    DispatchQueue.main.async {
        self.userData.child(phoneNumber).observeSingleEvent(of: .value, with: {(snapshot) in
            if snapshot.exists(){
                print("phone number exist")
                isRegistered = true
            }else{
                print("phone number doesn't exist")
                isRegistered = false
            }
        })
    }
    
    return isRegistered
}
  • `DispatchQueue.main.async` will run sometime in the future (on the main thread). The `userData.child.observeSingleEvent` is also contained within an a closure, which further suggests that there's no guarantee that the closure will be called before the func exits. In this case, you should be using a closure of your own to notify the caller when the value has been read – MadProgrammer Aug 05 '22 at 04:32

2 Answers2

0

try this simple and very common approach, using a completion handler:

func isPhoneNumberRegistered(phoneNumber: String, completion: @escaping (Bool) -> Void) { // <-- here
    DispatchQueue.main.async {
        self.userData.child(phoneNumber).observeSingleEvent(of: .value, with: {(snapshot) in
            if snapshot.exists(){
                print("phone number exist")
                completion(true) // <-- here
            }else{
                print("phone number doesn't exist")
                completion(false) // <-- here
            }
        })
    }
}

and use it like this:

isPhoneNumberRegistered(phoneNumber: "xxxx") { isRegistered in
    if isRegistered {
        print("yes registered")
    } else {
        print("not registered")
    }
}

You can also use the Swift async/await for asynchronous functions.

-1

This is a good case for using a semaphore. Just make sure not to call the function on the main queue. The main queue is a serial queue, and this on main queue will cause a deadlock.

func isPhoneNumberRegistered(phoneNumber: String) -> Bool {
  let semaphore = DispatchSemaphore(value: 1)
  var isRegistered = false
  
  DispatchQueue.main.async {
      self.userData.child(phoneNumber).observeSingleEvent(of: .value, with: {(snapshot) in
          if snapshot.exists(){
              print("phone number exist")
              isRegistered = true
          } else{
              print("phone number doesn't exist")
              isRegistered = false
          }
          semaphore.signal()
      })
  }
  semaphore.wait()
  return isRegistered
}
mani
  • 3,068
  • 2
  • 14
  • 25