1

I am working on a project using firebase database and I save the users with their displayName instead of uid. I check if the displayName of the user who is trying to signup is on the list of displayNames on firebase and if not I allow user to signup with that displayName.

here is my signUp function;

func signUp(email: String, password: String) {
    //gets the user data in the firebase
    Database.database().reference().child("users").observe(.value) { [self] (snapshot) in
        if snapshot.hasChild(self.userNameTxtField.text!){ //checking the displayName
            self.present(alertFunction(message: "Seçmiş olduğunuz kullanıcı adı daha önceden alınmış."), animated: true)
        } else {
            Auth.auth().createUser(withEmail: email, password: password) { (authResult, error) in
                if let error = error as NSError? {...} else {
                    self.signIn(email: email, password: password)
                }
            }
        }
    }
}

and here is my signIn function;

    func signIn(email: String, password: String) {
    
    Auth.auth().signIn(withEmail: email, password: password) { (authResult, error) in
        if let error = error as NSError? {...} else {
        
        self.activityIndicator.stopAnimating()
        self.view.isUserInteractionEnabled = true
        //create database reference
        self.ref = Database.database().reference()
        //create new child and write a value on the existance child
        if self.userNameTxtField.text == ""{
            print("User Name can not be nill!")
            self.present(self.alertFunction(message: "Kullanıcı adı boş bırakılamaz"), animated: true)
        } else {
            UserDefaults.standard.setValue(true, forKey: "userSignedIn")
            if let currentUser = Auth.auth().currentUser?.createProfileChangeRequest() {
                currentUser.displayName = self.userNameTxtField.text!
                currentUser.commitChanges(completion: { error in
                    if let error = error {
                        print(error)
                    } else {
                        print("DisplayName changed")
                        self.ref.child("users").child(currentUser.displayName!).setValue(["nickname": self.userNameTxtField.text ?? ""])
                        self.ref.child("users/\(currentUser.displayName!)/step_count").setValue(Int(0))
                        self.ref.child("users/\(currentUser.displayName!)/total_point").setValue(Int(0))
                        self.ref.child("users/\(currentUser.displayName!)/onesignal_player_id").setValue("")

                        self.performSegue(withIdentifier: "showMainFromRegister", sender: self)
                        }
                    })
                }
            }
        }
    }
}

and finally here is my actionFunction;

func alertFunction(message: String) -> UIAlertController {
    let alert = UIAlertController(title: "Uyarı!", message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Tamam", style: .cancel, handler: nil))
    self.activityIndicator.stopAnimating()
    self.view.isUserInteractionEnabled = true
    
    return alert
}

I call the signUp function after a button clicked and signUp func is calling the signIn function and if everything goes fine signIn function calls the performSegue function but after the performSegue

snapshot.hasChild(self.userNameTxtField.text!)

is triggered several time and the alert;

self.present(alertFunction(message: "Seçmiş olduğunuz kullanıcı adı daha önceden alınmış."), animated: true)

is displaying for no reason. How can I solve the problem?

1 Answers1

2

Replace

// listens for any change
.observe(.value) { [self] (snapshot) in

with

// listens for a change only once 
.observeSingleEvent(of: .value, with: { [weak self] snapshot in 
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87