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

Swift中如何在completion回调中为UITableViewCell赋值

解决方案

核心逻辑是让UITableView在异步数据拉取完成后再触发渲染,具体修改如下:

1. 调整viewDidLoad逻辑

初始化时将数据源数组置空,避免数据未加载完成时触发的渲染导致崩溃,在异步回调中填充数据源后主动刷新列表:

override func viewDidLoad() {
    super.viewDidLoad()
    // 提前设置tableView代理和数据源,若无请补充
    groupTableView.delegate = self
    groupTableView.dataSource = self
    // 初始数据源为空,不会触发cell渲染逻辑
    userArray = []
    
    AssignValueToUserObject { [weak self] in
        guard let self = self else { return }
        // 填充数据源,当前为单用户测试场景,后续多用户逻辑直接修改此处即可
        self.userArray = [user]
        // 所有UI操作必须在主线程执行,切换主线程刷新列表
        DispatchQueue.main.async {
            self.groupTableView.reloadData()
        }
    }
}

2. 完善数据拉取方法的回调逻辑

补充异常场景的回调触发,避免拉取失败时列表一直处于无数据状态,同时替换强解包逻辑避免崩溃:

extension MoneyGroupViewController {
    public func AssignValueToUserObject(completion: @escaping () -> Void) {
        // 获取用户id失败时也要触发回调
        guard let uid = Auth.auth().currentUser?.uid else {
            print("Could not get user id")
            completion()
            return
        }

        Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { [self] snapshot in
            // 使用defer保证所有分支都会触发回调
            defer {
                completion()
            }
            guard let dictionary = snapshot.value as? [String: AnyObject] else {
                print("用户数据格式解析失败")
                return
            }
            // 替换强解包为可选默认值,避免异常字段导致崩溃
            user.first_name = dictionary["first_name"] as? String ?? ""
            user.last_name = dictionary["last_name"] as? String ?? ""
            user.email = dictionary["email"] as? String ?? ""
            user.profile_picture = dictionary["profile_picture"] as? String
        }, withCancel: { error in
            print("数据拉取失败:\(error.localizedDescription)")
            // 拉取取消/失败时触发回调
            completion()
        })
    }
}

3. 优化Cell渲染逻辑(可选)

解决cell重用导致的头像错位、异常强解包崩溃问题:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = groupTableView.dequeueReusableCell(withIdentifier: "MoneyGroupTableViewCell", for: indexPath) as! MoneyGroupTableViewCell
    // 重置重用cell的旧头像,可替换为你的占位图资源
    cell.userImage.image = UIImage(named: "avatar_placeholder")
    
    let currentUser = userArray[indexPath.row]
    cell.userName.text = "\(currentUser.first_name) \(currentUser.last_name)"
    
    // 安全校验头像链接
    if let avatarStr = currentUser.profile_picture, !avatarStr.isEmpty, let avatarUrl = URL(string: avatarStr) {
        URLSession.shared.dataTask(with: avatarUrl, completionHandler: { data, _, error in
            guard let data = data, error == nil else { return }
            DispatchQueue.main.async {
                // 校验当前cell是否仍对应目标indexPath,避免重用错位
                guard let targetCell = tableView.cellForRow(at: indexPath) as? MoneyGroupTableViewCell else { return }
                targetCell.userImage.layer.cornerRadius = max(targetCell.userImage.frame.width, targetCell.userImage.frame.height)/2
                targetCell.userImage.layer.borderWidth = 1
                targetCell.userImage.image = UIImage(data: data)
            }
        }).resume()
    }
    return cell
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 07:00:04