Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Swift Firebase Firestore not able to get variable outside of embedded query

    • 0
    • 0
    • 0
    • 1
    • 0
    • 0
    • 0
    • 919
    Answer it

    Note: This is not a swiftUI

    I have a collection called **teamMembers** and another one called **patients**. In the **patients** document is an array field with a list of the **teamMembers** (document id). I am trying to set a toggle switch to **ON** in a TableView if a team member is in the array. 

    I can get the the team Member to print in the embedded query but I can't access it from outside that query. My thought is that if I can get the value outside of the inner query I can set the switch to on if it is true.

    The code is in func getTeamMembers()

     

    
    import UIKit
    import Firebase
    
    class ChooseTeamMemberViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
        
        
        //TODO: have populate from patient document field
        
        let db = Firestore.firestore()
        
        let dispatchGroup = DispatchGroup()
        
        
        @IBOutlet weak var GoBack: UIButton!
        @IBOutlet weak var tableView: UITableView!
        
        
        @IBOutlet weak var selectAllButton: UIButton!
        @IBOutlet weak var nextButton: UIButton!
        
        var teamMembers = [TeamMember]()
        var teamMemberList = [String]()
        
        
        var backSource = ""
        
        var patientID = ""
        
        var firstName = ""
        var middle = ""
        var lastName = ""
        var significantOther = ""
        var inER = ""
        var roomNumber = ""
        var status = ""
    
        var ArrvdHow = ""
        
        var selectAll = "OFF"
    
        var thisSwitch = ""
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            
            selectAllButton.layer.cornerRadius = 10
            nextButton.layer.cornerRadius = 10
            
            self.getTeamMembers()
        }
        
        func getTeamMembers() {
            db.collection(TEAMMEMBER_TABLE).order(by: FULL_NAME, descending: false).getDocuments() { (querySnapshot, err) in
                if let err = err {
                    print("Error getting documents: \(err)")
                } else {
                    guard let snap = querySnapshot else { return }
                    
                    for document in snap.documents {
                            
                            let fullName = document[FULL_NAME] as? String ?? ""
                            let email = document[EMAIL] as? String ?? ""
                            let isAdmin = document[IS_ADMIN] as? Bool ?? false
                            let teamMemberID = document.documentID
                            
                        var memberList = [String]()
                        let docRef = self.db.collection(PATIENT_TABLE)
                            .document(self.patientID)
    
                        docRef.getDocument { (result, error) in
                            
                            if let result = result, result.exists {
                                memberList = result[TEAM_MEMBER_LIST] as! [String]
                                
                                self.dispatchGroup.notify(queue: .main) {
                                    
                                    for member in memberList {
                                        if member == teamMemberID {
    
                                            self.thisSwitch = "true"
                                            
                                            // This prints fine:
                                            print("thisSwitch: \(self.thisSwitch)")
                                        }
                                    }
                                }
                            } else {
                                print("Document does not exist")
                            }
                        }
                        // This will not print the value:
                        print("phone: \(self.thisSwitch)")
                        let newTeamMember = TeamMember(fullName:  fullName, email:  email, phone:  self.thisSwitch, isAdmin:  isAdmin, teamMemberID: teamMemberID)
                        
                            self.teamMembers.append(newTeamMember)
    
                    }
                    self.tableView.reloadData()
                }
            }
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            // print(teamMembers.count)
            return teamMembers.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "chooseTeamCell", for: indexPath)
            
            let teamMember = teamMembers[indexPath.row]
            
            
            cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 22.0)
            cell.textLabel?.textColor = UIColor.themeColor
            cell.layer.backgroundColor = UIColor.clear.cgColor
            cell.textLabel?.text = teamMember.fullName
            
            // This will not print the value:
            print("row-self.thisSwitch: \(self.thisSwitch)")
            
            
            if patientID != "" {
                
                // Switch
                let switchView = UISwitch(frame: .zero)
                if teamMember.phone == "true" { switchView.setOn(true, animated: true) }
                if self.selectAll == "ON"{
                    switchView.setOn(true, animated: true)
                    db.collection("patients")
                        .document("\(self.patientID)").updateData(["teamMembers": FieldValue.arrayUnion(["\(teamMember.teamMemberID!)"])])
                } else {
                    switchView.setOn(false, animated: true)
                }
                
                
                switchView.tag = indexPath.row
                
                switchView.addTarget(self, action: #selector(self.switchChanged(_:)), for: .valueChanged)
                cell.accessoryView = switchView
            }
            
            
            return cell
        }
        
        @objc func switchChanged(_ sender: UISwitch!) {
            print("\(teamMembers[sender.tag].teamMemberID!) is switch to \(sender.isOn ? "ON" : "OFF")")
            
            if sender.isOn == true {
                
                db.collection("patients")
                   .document("\(self.patientID)").updateData(["teamMembers": FieldValue.arrayUnion(["\(teamMembers[sender.tag].teamMemberID!)"])])
                
            } else if sender.isOn == false {
                
                 db.collection("patients")
                    .document("\(self.patientID)").updateData(["teamMembers": FieldValue.arrayRemove(["\(teamMembers[sender.tag].teamMemberID!)"])])
                
            }
             
            
            
        }
        
        
        @IBAction func GoBack(_ sender: UIButton) {
            if backSource == "add" {
                self.backToAddNewPatient()
            } else {
                transitionToEditPatient()
            }
        }
        
        func backToAddNewPatient(){
            let addPatient = self.storyboard?.instantiateViewController(identifier: Constants.Storyboard.AddEditPatient) as? AddEditPatientPersonalInfoViewController
                
                
                addPatient?.patientID = self.patientID
                addPatient?.firstName = self.firstName
                addPatient?.middle = self.middle
                addPatient?.lastName = self.lastName
                
                addPatient?.significantOther = self.significantOther
                addPatient?.inER = self.inER
                addPatient?.roomNumber = self.roomNumber
                addPatient?.ArrvdHow = self.ArrvdHow
                addPatient?.status = self.status
                
                self.view.window?.rootViewController = addPatient
        }
        
        func transitionToEditPatient(){
            let editPat = self.storyboard?.instantiateViewController(identifier: Constants.Storyboard.editPatient) as? EditPatientPersonalInfoViewController
            
            editPat?.patientID = self.patientID
            editPat?.firstName = self.firstName
            editPat?.middle = self.middle
            editPat?.lastName = self.lastName
            
            editPat?.significantOther = self.significantOther
            editPat?.inER = self.inER
            editPat?.roomNumber = self.roomNumber
            editPat?.ArrvdHow = self.ArrvdHow
            editPat?.status = self.status
            
            self.view.window?.rootViewController = editPat
            self.view.window?.makeKeyAndVisible()
        }
        
        
        
        @IBAction func ChangeSelectAllButton(_ sender: UIButton) {
            self.selectAll = "ON"
            self.tableView.reloadData()
        }
        
        
        @IBAction func GoNextButton(_ sender: UIButton) {
            self.transitionToHospitalityItems()
        }
        
        func transitionToHospitalityItems(){
            let hospitalityItem = self.storyboard?.instantiateViewController(identifier: Constants.Storyboard.hospitalityItems) as? HospitalityItemsViewController
            
            
            hospitalityItem?.patientID = self.patientID 
            hospitalityItem?.firstName = self.firstName
            hospitalityItem?.middle = self.middle
            hospitalityItem?.lastName = self.lastName
            
            hospitalityItem?.significantOther = self.significantOther
            hospitalityItem?.inER = self.inER
            hospitalityItem?.roomNumber = self.roomNumber
            hospitalityItem?.ArrvdHow = self.ArrvdHow
            hospitalityItem?.status = self.status
            
            self.view.window?.rootViewController = hospitalityItem
            self.view.window?.makeKeyAndVisible()
        }
        
        
    }
    
    

     

 1 Answer(s)

  • This issue seems to be related to  multi-threading. The block passed to getDocument will be executed after the getDocument task is finished. Code written outside the block will be executed before the block is executed. Try moving this code:
    let newTeamMember = TeamMember(fullName:  fullName, email:  email, phone:  self.thisSwitch, isAdmin:  isAdmin, teamMemberID: teamMemberID)
    self.teamMembers.append(newTeamMember)

    after this line inside the block:
    self.thisSwitch = "true"
Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: