You need to enable JavaScript to run this app. Firebase获取的学校ID可在弹窗显示却无法在普通VC文本框展示
优惠活动
大模型
产品
解决方案
定价
更多

Firebase获取的学校ID可在弹窗显示却无法在普通VC文本框展示

核心问题定位

你遇到的文本框空白问题,本质是对Firestore getDocuments的异步执行时序理解偏差:

  • getDocuments属于异步网络请求,不会阻塞当前线程等待数据返回
  • 你当前的函数实现是:刚发起网络请求,不等回调里的赋值逻辑执行完成,就直接读取类成员变量skoolID的旧值做字符串截取、同步返回——此时网络请求尚未完成,skoolID还没被赋值,返回的自然是空字符串
  • 之前弹窗里能正常展示ID,属于偶发的时序巧合:要么是你之前已经在其他页面触发过同查询、提前完成了skoolsID的赋值,要么是弹窗弹出的延迟刚好赶上网络回调执行完成;换到独立页面调用时没有这些巧合,就直接暴露了空值问题。

现存的冗余脆弱逻辑

你当前通过把模型对象转字符串、再硬删除前后字符提取schoolID的写法非常不可靠:

  • 只要模型的默认字符串输出格式发生变化,截取位置就会完全错误
  • 完全没有必要绕这个弯,直接从查询结果中读取对应字段即可
可直接落地的修正方案
  1. 把获取ID的函数改为通过闭包回调返回结果,放弃无意义的同步return写法
  2. 移除硬截字符串的冗余逻辑,直接从查询结果中提取需要的school_id值
  3. 网络回调完成后,切回主线程完成UI文本框的赋值操作

改造后的通用ID获取函数

func fetchSchoolID(completion: @escaping (String?) -> Void) {
    guard let currentUserID = user?.uid else {
        completion(nil)
        return
    }
    db.collection("school_users")
        .whereField("userID", isEqualTo: currentUserID)
        .getDocuments { querySnapshot, err in
            if let err = err {
                print("There was an error fetching the documents: \(err)")
                completion(nil)
                return
            }
            guard let targetDoc = querySnapshot?.documents.first,
                  let schoolID = targetDoc.get("school_id") as? String else {
                completion(nil)
                return
            }
            completion(schoolID)
        }
}

新增事件页的正确调用逻辑

替换原viewDidLoad中的错误调用:

public override func viewDidLoad() {
    super.viewDidLoad()
    errLabel.alpha = 0
    
    fetchSchoolID { [weak self] schoolID in
        // 网络回调不在主线程,UI操作必须切回主线程执行
        DispatchQueue.main.async {
            self?.schoolIDTextF.text = schoolID ?? ""
        }
    }
}

兼容原有弹窗逻辑的调用方式

如果要保留原弹窗的展示效果,直接复用上面的通用函数即可,不用维护两份重复代码:

@IBAction func infoPressed(_ sender: UIBarButtonItem) {
    let alert = UIAlertController(title: "User Info", message: "School ID", preferredStyle: .alert)
    let dismissAction = UIAlertAction(title: "Dismiss", style: .cancel) { _ in
        self.dismiss(animated: true, completion: nil)
    }
    alert.addTextField { alertTextField in
        alertTextField.isEnabled = false
        // 等异步拿到ID后再给弹窗文本框赋值
        self.fetchSchoolID { schoolID in
            DispatchQueue.main.async {
                alertTextField.text = schoolID ?? ""
            }
        }
    }
    alert.addAction(dismissAction)
    present(alert, animated: true, completion: nil)
}

额外提醒:原代码中连续两次调用getTheSchoolID()的写法,除了拿不到异步值的问题,还会重复发起两次完全相同的网络请求,造成不必要的流量消耗。


内容的提问来源于stack exchange,提问作者dsonawave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 08:27:02