如何判断删除的是数组最后一个元素?CollectionView隐藏问题求助
问题分析与解决方案
核心问题点
- 最后一个元素判断逻辑错误:依赖
messages.last == messages[indexPath.row]的内容对比方式,若数组存在重复元素会误判,且无法精准对应下标位置 - 数组越界崩溃:删除元素后额外调用
collectionView.reloadData(),导致数据源更新时序混乱,引发索引不匹配 - containerView未隐藏:
hideTickerViewCallback仅在reloadTicker方法的特定分支中赋值,删除操作触发时可能因回调未绑定而无法执行隐藏逻辑
修复后的CollectionView删除逻辑代码
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withClass: TickerCell.self, for: indexPath) let message = messages[indexPath.row] cell.set(message: message) cell.tickerCellCallback = { [weak self] in guard let strongSelf = self else { return } // 先校验下标合法性,彻底避免越界 guard indexPath.row < strongSelf.messages.count else { return } // 执行元素删除与UI更新 strongSelf.messages.remove(at: indexPath.row) collectionView.deleteItems(at: [indexPath]) // 直接检查数组是否为空,触发隐藏回调 if strongSelf.messages.isEmpty { strongSelf.hideTickerViewCallback?() } // 移除冗余的reloadData,deleteItems已能正确同步UI与数据源 } return cell } func reloadData() { collectionView.reloadData() }
修复后的ViewController隐藏逻辑代码
private func reloadTicker() { tickerView.messages = homeViewModel.inboxMessages // 直接根据数据源状态设置初始隐藏状态 tickerView.isHidden = homeViewModel.inboxMessages.isEmpty // 提前绑定回调,确保删除操作触发时回调始终存在 tickerView.hideTickerViewCallback = { [weak self] in UIView.animate(withDuration: 0.3) { self?.tickerView.isHidden = true } } tickerView.reloadData() }
关键修复说明
- 下标合法性校验:删除前先判断
indexPath.row < messages.count,规避异步回调或数据源变更导致的越界风险 - 简化空数组判断:删除后直接检查
messages.isEmpty,无需依赖元素内容对比,逻辑更可靠 - 移除冗余reloadData:
deleteItems(at:)会自动同步collectionView的UI与数据源索引,重复调用reloadData会引发索引混乱 - 提前绑定回调:将回调赋值移至分支判断外,确保无论初始状态如何,删除操作都能触发隐藏逻辑
- 简化动画写法:用
animate(withDuration:)替代animateKeyframes,适配简单动画场景
内容的提问来源于stack exchange,提问作者ferryawijayanto
相关产品推荐
相关产品推荐

