I'm building an application where a user can store companies information (like name, address, latitude, longitude to a Firebase real-time database). 
With that information, those companies are then presented in a map as annotations.
My viewDidLoad is shown below
override func viewDidLoad() {
    super.viewDidLoad()
    // Definitions
    let autenticacao = Auth.auth()
    let idUsuarioLogado = (autenticacao.currentUser?.uid)!
    let database = Database.database().reference()
    let usuarios = database.child("usuarios")
    let clinicas = database.child("clinicas")
    // Map - User location
    self.mapa.delegate = self
    self.gerenciadorLocalizacao.delegate = self
    self.gerenciadorLocalizacao.desiredAccuracy = kCLLocationAccuracyBest
    self.gerenciadorLocalizacao.requestWhenInUseAuthorization()
    self.gerenciadorLocalizacao.startUpdatingLocation()
    // retrieve user information
    usuarios.child(idUsuarioLogado).observe(DataEventType.value) { (snapshot) in
        let dados = snapshot.value as? NSDictionary
        let emailUsuario = dados?["email"] as! String
        let nomeUsuario = dados?["nome"] as! String
        let perfilUsuario = dados?["perfil"] as! String
        let idUsuario = snapshot.key
        let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
        print("User profile \(perfilUsuario)")
    }
    // Clinicas listeners
    clinicas.observe(DataEventType.childAdded) { (snapshot) in
        let dados = snapshot.value as? NSDictionary
        //print("Dados na leitura \(dados)")
        let clinica = Clinica()
        clinica.identificador = snapshot.key
        clinica.nome = dados?["nome"] as! String
        clinica.endereco = dados?["endereco"] as! String
        clinica.cidade = dados?["cidade"] as! String
        clinica.cep = dados?["cep"] as! String
        clinica.estado = dados?["estado"] as! String
        clinica.latitude = dados?["latitude"] as! String
        clinica.longitude = dados?["longitude"] as! String
        clinica.urlImagem = dados?["urlImagem"] as! String
        clinica.idImagem = dados?["idImagem"] as! String
        self.clinicasR.append(clinica)
    }
    // add annotations to the map
    for oneObject in self.todasAnotacoes {
        print("Oneobj \(oneObject)")
        let umaAnotacao = MinhaAnotacao()
        var oneObjLoc: CLLocationCoordinate2D = CLLocationCoordinate2DMake(oneObject.objLat, oneObject.objLong)
        umaAnotacao.coordinate = oneObjLoc
        umaAnotacao.title = oneObject.objName
        umaAnotacao.subtitle = oneObject.objDesc
        umaAnotacao.category = oneObject.objCat
        self.anotacaoArray.append(umaAnotacao)
        self.mapa.addAnnotations(self.anotacaoArray)
    }
}
My viewDidLoad is "structured" in 4 main blocks (even though they run in a different order given they are asynchronous):
- Definition;
- Retrieve user profile;
- Retrieve companies information (name, latitude, longitude);
- Add annotations to the map.
As those are asynchronous functions, they run in different order and this is what is causing trouble to me. note: There is still one piece missing here that is to feed all annotations to the variable todasAnotacoes which I'll do once I can retrieve data before triggering add annotation "block".
As annotation info comes from the firebase database, I should only have it executed once the clinicas.observe(DataEventType.childAdded) { (snapshot) in is concluded.
As is today, the sequence Xcode runs is:
- Definitions
- Add annotations;
- retrieve data from firebase with companies details
I've tried adding the add annotation block to the closure, adding a dispatchqueue but none of those really worked. I also did a lot os search in stackoverflow but I couldn't find anything that i can use (or I wasn't able to understand).
So, in summary I need to run the add annotations after retrieving all data from Firebase.
Any ideas on how I could do that?
EDIT 1 - Final code with the suggested updates
override func viewDidLoad() {
    super.viewDidLoad()
    // Retrieving Logger user data and hidding "add" button if applicable
    ProgressHUD.show("Carregando...")
    let autenticacao = Auth.auth()
    let idUsuarioLogado = (autenticacao.currentUser?.uid)!
    let database = Database.database().reference()
    let usuarios = database.child("usuarios")
    var isUserLoaded = false
    var isClinicsLoaded = false
    usuarios.child(idUsuarioLogado).observe(DataEventType.value) { (snapshot) in
        let dados = snapshot.value as? NSDictionary
        let emailUsuario = dados?["email"] as! String
        let nomeUsuario = dados?["nome"] as! String
        let perfilUsuario = dados?["perfil"] as! String
        let idUsuario = snapshot.key
        let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
        isUserLoaded = true
        if (isUserLoaded && isClinicsLoaded) {
            self.addAnnotationsToMap();
        }
        //print("\(usuario.email) e \(usuario.nome) e \(usuario.uid) e \(usuario.perfil)")
    }
    // Option to code above
    /*if Auth.auth().currentUser != nil {
     if let uid = (Auth.auth().currentUser?.uid) {
     let database = Database.database().reference()
     let usuarios = database.child("usuarios").child(uid)
     usuarios.observe(.value) { (snapshot) in
     let dados = snapshot.value as? NSDictionary
     let emailUsuario = dados?["email"] as! String
     let nomeUsuario = dados?["nome"] as! String
     let perfilUsuario = dados?["perfil"] as! String
     let idUsuario = snapshot.key
     let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
     print("Got here \(usuario.email) e \(usuario.nome) e \(usuario.uid) e \(usuario.perfil)")
     if perfilUsuario != "admin" {
     self.navigationItem.rightBarButtonItems?.remove(at: 1)
     print("Disable + Button")
     }
     }
     }
     }*/
    // Map - User location
    self.mapa.delegate = self
    self.gerenciadorLocalizacao.delegate = self
    self.gerenciadorLocalizacao.desiredAccuracy = kCLLocationAccuracyBest
    self.gerenciadorLocalizacao.requestWhenInUseAuthorization()
    self.gerenciadorLocalizacao.startUpdatingLocation()
    let clinicas = database.child("clinicas")
    // Clinicas listeners
    clinicas.observe(DataEventType.value) { (snapshots) in
        for child in snapshots.children {
            let snapshot = child as! DataSnapshot
            print("Clinicas Mapeadas - end")
            let dados = snapshot.value as? NSDictionary
            //print("Dados na leitura \(dados)")
            let clinica = Clinica()
            clinica.identificador = snapshot.key
            clinica.nome = dados?["nome"] as! String
            clinica.endereco = dados?["endereco"] as! String
            clinica.cidade = dados?["cidade"] as! String
            clinica.cep = dados?["cep"] as! String
            clinica.estado = dados?["estado"] as! String
            clinica.latitude = dados?["latitude"] as! String
            clinica.longitude = dados?["longitude"] as! String
            clinica.urlImagem = dados?["urlImagem"] as! String
            clinica.idImagem = dados?["idImagem"] as! String
            self.clinicasR.append(clinica)
            self.todasAnotacoes.append((objLat: Double(clinica.latitude) as! CLLocationDegrees, objLong: Double(clinica.longitude) as! CLLocationDegrees, objName: clinica.nome, objDesc: clinica.endereco, objId: clinica.identificador))
        }
        isClinicsLoaded = true
        if (isUserLoaded && isClinicsLoaded) {
            self.addAnnotationsToMap();
        }
    }
    /* NOT IN USE FOR NOW
     let latitude = Double(-23.623558)
     let longitude = Double(-46.580787)
     let localizacao: CLLocationCoordinate2D = CLLocationCoordinate2D.init(latitude: latitude, longitude: longitude)
     let span: MKCoordinateSpan = MKCoordinateSpan.init(latitudeDelta: 0.01, longitudeDelta: 0.01)
     let regiao = MKCoordinateRegion.init(center: localizacao, span: span)
     self.mapa.setRegion(regiao, animated: true)*/
    ProgressHUD.dismiss()
}
// add annotations to the map
func addAnnotationsToMap() {
    anotacaoArray = []
    for oneObject in self.todasAnotacoes {
        for oneObject in self.todasAnotacoes {
            // print("Oneobj \(oneObject)")
            let umaAnotacao = MinhaAnotacao()
            var oneObjLoc: CLLocationCoordinate2D = CLLocationCoordinate2DMake(oneObject.objLat, oneObject.objLong)
            umaAnotacao.coordinate = oneObjLoc
            umaAnotacao.title = oneObject.objName
            umaAnotacao.subtitle = oneObject.objDesc
            umaAnotacao.identicadorMapa = oneObject.objId
            self.anotacaoArray.append(umaAnotacao)
            print("Annotation added \(todasAnotacoes.count) - end")
        }
        self.mapa.addAnnotations(self.anotacaoArray)
        self.todasAnotacoes = []
        self.anotacaoArray = []
        // print("Annotations added 2 - end")
    }
}
 
    