Swift中tableView内嵌collectionView新增4个cell后reloadData顺序异常
问题原因
主要由3个错误实现逻辑共同导致:
- 没有独立维护collectionView的数据源,完全依赖cell存储输入内容。collectionView的cell是复用机制,当cell数量增加到超出屏幕可见范围、或者调用
reloadData()刷新时,复用的旧cell会携带之前的内容,导致展示顺序错乱。 - 用
cell.tag标记cell对应的序号,cell复用时tag不会自动更新为当前对应位置的序号,会导致数据存储和展示的匹配错位。 myRepsTextChanged方法中遍历所有indexPath调用cellForItem(at:)取cell,这个方法只能获取当前可见的cell,不可见的cell会返回nil,强制转换会触发崩溃,就算未崩溃也会拿到复用的旧cell数据,导致存储顺序错乱。
解决方案
1. 搭建独立数据源
声明专属的数组存储每个cell对应的数据,不要依赖cell存业务内容:
// 自定义模型,按需调整属性 struct SetModel { var reps: String var index: Int } // 数据源数组 var setList: [SetModel] = []
2. 优化新增cell逻辑
新增时不要全量刷新,改用局部插入的方式,避免打乱现有cell的状态:
@IBAction func addSetButtonPressed(_ sender: Any) { numberOfSets += 1 Constants.Other.numberOfTotaSest += 1 // 新增数据先存入数据源 setList.append(SetModel(reps: "", index: numberOfSets - 1)) // 局部插入新cell,性能更高也不会打乱现有cell内容 collectionView.insertItems(at: [IndexPath(row: numberOfSets - 1, section: 0)]) }
3. 调整输入变更存储逻辑
不要遍历所有cell取数据,在cellForItemAt中给输入框绑定对应位置的序号,输入变更时直接更新对应位置的数据源:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell let model = setList[indexPath.row] cell.repsText.text = model.reps // 给输入框绑定当前行号,不要给cell加tag cell.repsText.tag = indexPath.row cell.repsText.addTarget(self, action: #selector(myRepsTextChanged(_:)), for: .editingChanged) return cell } @objc func myRepsTextChanged(_ tf: UITextField) { let currentRow = tf.tag guard currentRow < setList.count else { return } // 直接更新对应位置的数据源 setList[currentRow].reps = tf.text ?? "" // 同步到全局常量 if !Constants.Other.duplicateFound { // 如果是新增输入就加,是修改就替换,按需调整逻辑 if currentRow < Constants.Other.setsFromCollectionView.count { Constants.Other.setsFromCollectionView[currentRow] = [tf.text ?? "", currentRow] } else { Constants.Other.setsFromCollectionView.append([tf.text ?? "", currentRow]) } } }
4. 兼容全量刷新场景
如果业务需要调用reloadData()全量刷新,确保刷新前所有输入内容已经同步到setList数据源,刷新后cell会从数据源取最新内容,不会出现顺序错乱。
内容的提问来源于stack exchange,提问作者Bruce Simmons
相关产品推荐
相关产品推荐

