Why print outside observe block is executed before print(count) inside observe block?

Viewed 57
func teacherExists(teacherName: String) -> Bool
    {
        var dataBaseRef2: DatabaseReference!
        dataBaseRef2 = Database.database().reference()
        let teachersTableRef = dataBaseRef2.child("teachers")
        self.teachersList.removeAll()
        teachersTableRef.observeSingleEvent(of: DataEventType.value, with: { (snapshot) in

       // teachersTableRef.observe(.value)
        //{
          //  snapshot in
            let teachersNamesDictionary = snapshot.value as? [String: Any] ?? [:]
            for(key, _) in teachersNamesDictionary
            {
                if let teacherDict = teachersNamesDictionary[key] as? [String: Any]
                {
                    if let teacher = Teacher(dictionary: teacherDict)
                    {
                        //print(teacher.teacher_name)
                        self.teachersList.append(teacher.teacher_name)
                    }
                }
            }
            print(self.teachersList.count)
        })
        print("Outside \(self.teachersList)")
        return false
    }
3 Answers

Because Firebase APIs are all asynchronous. It would be bad for your app if they blocked your code path, because that could cause your app to hang indefinitely.

observeSingleEvent returns immediately, and the passed observer gets invoked some time later, whenever the data is finally ready. Execution continues on the next line, which prints to the console.

You can use closure to callback after check for duplicate

func teacherExists(teacherName: String, completion: @escaping ((Bool) -> Void)) -> Void {
    var dataBaseRef2: DatabaseReference!
    dataBaseRef2 = Database.database().reference()
    let teachersTableRef = dataBaseRef2.child("teachers")
    self.teachersList.removeAll()
    teachersTableRef.observeSingleEvent(of: DataEventType.value, with: { (snapshot) in

        let teachersNamesDictionary = snapshot.value as? [String: Any] ?? [:]
        for(key, _) in teachersNamesDictionary
        {
            if let teacherDict = teachersNamesDictionary[key] as? [String: Any]
            {
                if let teacher = Teacher(dictionary: teacherDict)
                {
                    //print(teacher.teacher_name)
                    self.teachersList.append(teacher.teacher_name)
                }
            }
        }
        let exists = self.teachersList.contains(teacherName)
        completion(exists)
    })
}

And call function as below

teacherExists(teacherName: newTeacherName) { (exists) in
    if exists {
        // show alert
    } else {
        // add new teacher to db
    }
}

Hope it help!

getting error upon calling teacherExists function

let OKAction = UIAlertAction(title: "OK", style: .default, handler:
    {
        (action: UIAlertAction!) ->Void in
        let textfield = alert.textFields![0] as UITextField
        newTeacherName = textfield.text!.uppercased()
        if !(newTeacherName.isEmpty)
        {
            //checking if teacher already exists using function teacherExists
            let exists = self.teacherExists(teacherName: newTeacherName, completion:

            if exists == true //if duplicate teacher is found
            {
                let alert = UIAlertController(title: "Duplicate Teacher", message: "Teacher \(newTeacherName) has been added earlier", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }
            else
            {
                //add teacher to database here
                let dict = ["teacher_name" : newTeacherName]
                let newTeacher = Teacher(dictionary: dict)
                let tableRef = self.dataBaseRef.child("teachers") //getting reference of node with name teachers
                let recordRef = tableRef.childByAutoId() //creating a new record in teachers node
                recordRef.setValue(newTeacher!.toDictionary())//adding data to new record in teachers node
            }
        }
    })
Related