How to display school ID in the textfield?

145 Views Asked by At

I want to display the school id in a textfield of a certain view controller but I can't for some reason. I have a function that gets the school ID, of the current School user, and I am able to display it in an alertVC but not a regular VC. I will add images and explanations.

First, I will show my code for the function that gets the school ID for the current user and displays it in the alertVC.

  func getTheSchoolsID() -> String {
    db.collection("school_users").whereField("userID", isEqualTo: user?.uid).getDocuments { (querySnapshot, err) in
        if let err = err {
            print("There was an error fetching the documents: \(err)")
        } else {
            self.skoolsID = querySnapshot!.documents.map { document in
                return SchoolID(schoolID: (document.get("school_id") as! String ?? ""))
            }
            self.tableView.reloadData()
        }
    }
    let fixID = "\(skoolsID)"
    let substring = fixID.dropFirst(28).dropLast(3)
    let realString = String(substring)
    
    return realString
}

Here is the code for the alertVC as well.

@IBAction func infoPressed(_ sender: UIBarButtonItem) {
    var text = UITextField()
    
    let alert = UIAlertController(title: "User Info", message: "School ID", preferredStyle: .alert)
    let action = UIAlertAction(title: "Dismiss", style: .cancel) { (action) in
        self.dismiss(animated: true, completion: nil)
    }
    alert.addTextField { (alertTextField) in
        alertTextField.text = self.getTheSchoolsID()
        alertTextField.isEnabled = false
       
        
        
    }
    alert.addAction(action)
    present(alert, animated: true, completion: nil)
}

These two produce this outcome. Positive Outcome

This is the exact school_id that is in the document as well.

Now, when I want to display this exact same value in a textfield of the other VC where I add a new event, it shows nothing.

Negative Outcome

The code is exactly the same as the first code snippet, except for reloadData(), which makes sense, and It doesn't produce the same outcome.

func getTheSchoolID() -> String {
    db.collection("school_users").whereField("userID", isEqualTo: user?.uid).getDocuments { (querySnapshot, err) in
        if let err = err {
            print("There was an error fetching the documents: \(err)")
        } else {
            self.skoolID = querySnapshot!.documents.map { document in
                return SchoolID(schoolID: (document.get("school_id") as! String ?? ""))
            }
        }
    }

   
    
    let fixedID = "\(skoolID)"
    let substring = fixedID.dropFirst(28).dropLast(3)
    let realString = String(substring)
    return realString
}

Here is me trying to declare it as well.

   public override func viewDidLoad() {
    super.viewDidLoad()
    
    errLabel.alpha = 0
    
    getTheSchoolID()
    
    
    
    schoolIDTextF.text = getTheSchoolID()
    // Do any additional setup after loading the view.
}

If anybody can help with this problem it would be greatly appreciated. I tried to explain it as best as I possibly could. I know there's a lot of information, but if you still need more I can clarify in the comments. Thanks.

2

There are 2 best solutions below

0
On BEST ANSWER

GetSchoolIds from the firestore collection is the asynchronous task. So using the closure you can achieve this.

  func getTheSchoolsID(completion:@escaping(_ schoolIds:[SchoolID]?) -> Void) {
        db.collection("school_users").whereField("userID", isEqualTo: user?.uid).getDocuments { (querySnapshot, err) in
            if let err = err {
                print("There was an error fetching the documents: \(err)")
                completion(nil)
            } else {
                let schoolsId = querySnapshot!.documents.map { document in
                    return SchoolID(schoolID: (document.get("school_id") as! String ?? ""))
                }
                completion(schoolsId)
            }
        }
    }

Use this function to your VC

override func viewDidLoad() {
    super.viewDidLoad()
    
    errLabel.alpha = 0
    
    getTheSchoolsID(completion: {
       [weak self] schoolIds in
        if let schoolIdObj = schoolIds?.first {
        let substring = schoolIdObj.schoolID.dropFirst(28).dropLast(3)
        let realString = String(substring)

          DispatchQueue.main.async {
            self?.schoolIDTextF.text = realString 
          }
        }
    })
}
4
On

The issue lies in the async Firebase code. Use closures or completion handler to get the result.

Modify your getSchoolId as

    func getTheSchoolID(completion: @escaping ((String?) -> ())) {
        db.collection("school_users").whereField("userID", isEqualTo: user?.uid).getDocuments { (querySnapshot, err) in
            if let err = err {
                print("There was an error fetching the documents: \(err)")
                completion(nil)
            } else {
                self.skoolID = querySnapshot!.documents.map { document in
                    return SchoolID(schoolID: (document.get("school_id") as! String ?? ""))
                }
            }
        }
        
        let fixedID = "\(skoolID)"
        let substring = fixedID.dropFirst(28).dropLast(3)
        let realString = String(substring)
        completion(realString)
    }

And in your VC, use it as

override func viewDidLoad() {
    super.viewDidLoad()
    
    errLabel.alpha = 0
    
    getTheSchoolID(completion: {
       [weak self] schoolId in
        if let id = schooldId {
          DispatchQueue.main.async {
            self?.schoolIDTextF.text = id 
          }
        }
    })
}