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

Swift:TableView传数据到CollectionView时添加异常及删除崩溃问题

问题排查与解决方案

咱们先拆解你遇到的两个核心问题:点击TableView任意行都重复添加顶部用户、CollectionView删除条目时崩溃,一步步来解决:

1. 解决重复添加错误用户的问题

从你的代码逻辑来看,tableView(_:didSelectRowAt:)里的user = users[indexPath.row]本身是正确的,但出现“无论点哪行都加顶部用户”的情况,大概率是协议代理的使用出了问题——你定义了toRefresh协议,但没看到代理设置的代码,导致数据传递的实例不统一,或者直接操作数组的方式有问题。

先修正协议的使用逻辑,确保数据能正确传递:

// 给协议加个专属前缀,避免和系统方法冲突
protocol UserSelectionDelegate: AnyObject {
    func didSelectUser(_ user: User)
}

// 在TableView所在的ViewController中添加代理属性
weak var delegate: UserSelectionDelegate?

// 修改TableView的选中方法
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let selectedUser = users[indexPath.row]
    // 通过代理传递选中用户,而非直接操作外部数组
    delegate?.didSelectUser(selectedUser)
    tableView.deselectRow(at: indexPath, animated: true) // 取消选中状态,提升体验
}

然后在CollectionView所在的ViewController中遵守代理,实现方法:

class CollectionViewController: UIViewController, UserSelectionDelegate {
    var chosenUser: [User] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 绑定代理:获取你的TableView所在VC实例,设置其delegate为当前VC
        let tableVC = // 这里替换成你获取TableViewVC的逻辑
        tableVC.delegate = self
    }
    
    func didSelectUser(_ user: User) {
        // 可选:添加重复判断,避免同一个用户被多次添加
        if !chosenUser.contains(where: { $0.id == user.id }) {
            chosenUser.append(user)
            updateCollectionView()
        }
    }
    
    func updateCollectionView() {
        collectionView.reloadData()
    }
}

这样就能保证选中的用户是正确传递的,不会出现乱加的情况。

2. 解决CollectionView删除崩溃的问题

你现在的删除逻辑顺序完全反了!UICollectionView的更新规则是必须先修改数据源,再调用UI更新方法,你先调用deleteItems(at:)时,CollectionView的数据源还是旧的,直接导致索引越界崩溃。

修正后的删除代码:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    // 第一步:先修改数据源
    chosenUser.remove(at: indexPath.item)
    // 第二步:再调用CollectionView的删除方法
    collectionView.deleteItems(at: [indexPath])
    // 不需要额外调用reloadData,deleteItems会自动更新UI
}

你的numberOfItemsInSection返回chosenUser.count是正确的,这部分不用改。

额外优化建议

  • 给User模型实现Equatable协议,让重复判断更简洁:
struct User: Equatable {
    let id: Int
    let name: String
    // 其他属性
    
    static func == (lhs: User, rhs: User) -> Bool {
        return lhs.id == rhs.id
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:33:48