Swift UICollectionView代理新建Cell导致样式修改无效问题修复
问题原因
你现在的代码有两个核心问题导致UI修改不生效:
- 业务类
CheckInSystem违反职责边界,自己初始化了一个完全没有加入CollectionView视图层级的CheckInCell实例传给代理,修改这个游离实例的属性根本不会影响界面上真实显示的cell - 代码里漏了
CheckInSystem的代理绑定步骤,且UICollectionViewDataSource的必要方法没补全、视图获取逻辑放错了层级
修复方案
按以下步骤修改即可:
- 第一步:调整代理协议定义,业务层不需要传递UI对象,只需要通知视图层触发对应操作即可
protocol AnimateTheLastCheckInDayDelegate: AnyObject{ // 删除传cell的参数,业务层不关心UI实现细节 func animateLastDay() }
- 第二步:给CheckInSystem绑定代理,修正现有错误的系统方法写法
首先在控制器里新增一个标记位,处理目标cell未加载到屏幕时的高亮逻辑,同时修正viewDidAppear的错误写法,在viewDidLoad中绑定代理:
class CheckInViewController: UIViewController { let checkInSystem = CheckInSystem() let collectionView = UICollectionView() // 新增:标记是否需要高亮最后一个打卡cell private var shouldHighlightLastCheckInCell = false // 替换成你自己的打卡数据源数组 private var checkInDataList: [CheckInModel] = [] override func viewDidLoad() { super.viewDidLoad() // 其他collectionView注册、布局代码省略 // 绑定代理,这步你之前漏了 checkInSystem.animateTheLastCheckInDayDelegate = self } // 修正你之前写错的viewDidAppear方法 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) checkInSystem.lala() } //... 其他原有代码 }
- 第三步:修改CheckInSystem的回调逻辑,去掉新建cell的错误代码
class CheckInSystem{ weak var animateTheLastCheckInDayDelegate: AnimateTheLastCheckInDayDelegate? func lala(){ // 只触发回调通知代理,不要在这里创建任何UI对象 animateTheLastCheckInDayDelegate?.animateLastDay() } }
- 第四步:补全UICollectionViewDataSource的缺失方法,在代理回调中获取真实显示的cell做修改
extension CheckInViewController: UICollectionViewDataSource { // 补全你之前缺失的数据源方法 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return checkInDataList.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CheckInCell.identifier, for: indexPath) as! CheckInCell // 原有cell数据绑定逻辑省略,比如给cell绑定打卡日期、状态等 // 处理cell未加载时的高亮逻辑 let lastItemIndex = checkInDataList.count - 1 if shouldHighlightLastCheckInCell && indexPath.item == lastItemIndex { cell.backgroundColor = .red // 高亮执行完重置标记 shouldHighlightLastCheckInCell = false } // 你之前漏了return cell,会直接触发崩溃 return cell } } extension CheckInViewController: AnimateTheLastCheckInDayDelegate{ func animateLastDay() { let lastItemIndex = checkInDataList.count - 1 guard lastItemIndex >= 0 else { return } let targetIndexPath = IndexPath(item: lastItemIndex, section: 0) // 先尝试获取当前已经在屏幕上显示的目标cell if let targetCell = collectionView.cellForItem(at: targetIndexPath) as? CheckInCell { targetCell.backgroundColor = .red print(1233254234) return } // 如果cell还没加载到屏幕上,打标记等cell渲染时再高亮 shouldHighlightLastCheckInCell = true } }
注意事项
业务逻辑层不要持有、创建任何UIKit视图对象,所有UI操作都应该在控制器/视图层完成,避免业务和UI耦合,也能避免出现修改游离视图导致UI不更新的问题。
内容的提问来源于stack exchange,提问作者fonzyara
相关产品推荐
相关产品推荐

