You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift弹窗UITableView仅调用一次reloadData()的问题求助

问题分析与解决方案

让我来帮你排查下问题所在,你的代码里有几个关键问题导致了cellForRowAt从未执行的现象:

1. UITableView实例被重新创建,丢失了DataSource和Delegate

你在viewDidLoad中给全局的tblTeams设置了dataSource和delegate,但在ShowTeams方法里又执行了:

tblTeams = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 180))

这行代码会创建一个全新的UITableView实例,并覆盖原来的全局变量,而这个新实例并没有设置dataSource和delegate!所以弹窗里展示的表格视图根本没有绑定代理方法,自然不会调用cellForRowAt,而你看到的numberOfRowsInSection被调用一次,大概率是旧的、未被展示的表格实例触发的。

解决方法:

要么复用全局的tblTeams实例(推荐),要么给新创建的实例重新设置代理:

方案A:复用全局实例

把ShowTeams里的表格初始化代码改成:

// 不要重新创建实例,直接修改已有实例的frame
tblTeams.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 180)

同时把tblTeams.register(...)移到viewDidLoad里,只执行一次:

override func viewDidLoad() {
    super.viewDidLoad()
    tblTeams.dataSource = self
    tblTeams.delegate = self
    tblTeams.register(UITableViewCell.self, forCellReuseIdentifier: "cellTeams") // 移到这里
    RefreshData()
}

方案B:给新实例设置代理

如果坚持要重新创建实例,记得添加代理设置:

tblTeams = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 180))
tblTeams.dataSource = self // 新增
tblTeams.delegate = self   // 新增
tblTeams.register(UITableViewCell.self, forCellReuseIdentifier: "cellTeams")

2. 异步数据加载的时机问题

你的RefreshData方法里用循环多次调用Firestore的getDocuments,每次都是异步请求,但你在每个请求完成后就调用reloadData()。这会导致:

  • 表格可能在数据还没完全加载完就刷新,显示的行数不准确
  • 多次调用reloadData(),造成不必要的性能消耗

解决方法:

用DispatchGroup等待所有异步请求完成后,统一刷新表格:

func RefreshData(){
    let db = Firestore.firestore()
    guard let uid = Auth.auth().currentUser?.uid else {
        print("用户未登录")
        return
    }
    dataTeams.removeAll() // 清空现有数据
    let dispatchGroup = DispatchGroup()
    
    // 用for-in循环替代while,更符合Swift风格
    for i in 1...6 {
        dispatchGroup.enter() // 进入分组
        db.collection("teams").whereField("uid\(i)", isEqualTo: uid)
            .getDocuments() { (querySnapshot, err) in
                defer { dispatchGroup.leave() } // 不管成功失败都要离开分组
                if let err = err {
                    print("获取uid\(i)的团队数据失败:\(err)")
                } else {
                    for document in querySnapshot!.documents {
                        // 安全解包,避免强制解包崩溃
                        if let username = document["username"] as? String {
                            self.dataTeams.append(username)
                        } else {
                            print("警告:文档\(document.documentID)缺少username字段")
                        }
                    }
                }
        }
    }
    
    // 所有请求完成后,在主线程刷新表格
    dispatchGroup.notify(queue: .main) {
        print("所有团队数据加载完成,共\(self.dataTeams.count)条")
        self.tblTeams.reloadData()
    }
}

3. 其他优化建议

  • 尽量避免强制解包(比如document["username"] as? String!),改用可选绑定,防止数据格式错误导致崩溃
  • 在ShowTeams方法中,弹窗展示前确保表格已经设置好所有属性(比如rowHeight、separatorColor等)
  • 如果你的页面只有这一个UITableView,可以去掉代理方法里的tableView == tblTeams判断,简化代码

按照以上修改后,你的表格应该能正常加载数据并展示cell了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:30:49