如何在UICollectionView的didSelectItemAt中调用viewWillTransition取Cell中心
解决方案:提取复用方法,避免手动调用生命周期函数
别直接调用viewWillTransition哦,这是UIKit专门用来处理设备旋转的生命周期方法,手动触发它可能会干扰系统的旋转流程,引发意料之外的布局问题或者生命周期事件。我们可以把「获取选中Cell中心」的逻辑抽成一个独立的私有方法,让旋转和点击场景都复用这个方法,这样就能保证center变量始终持有有效的值了。
步骤1:提取复用方法
先写一个专门用来更新选中Cell中心的方法,同时处理可选值的安全解包(避免你之前代码里强制解包可能导致的崩溃):
private func updateSelectedCellCenter() { // 先判断是否有选中的Cell guard let selectedIndexPath = categoryCV.indexPathsForSelectedItems?.first else { center = .zero // 没有选中的话可以设为原点,或者根据你的需求处理 return } // 安全获取Cell的布局属性 if let cellAttributes = categoryCV.layoutAttributesForItem(at: selectedIndexPath) { center = cellAttributes.center print("Updated Center: \(center)") } else { center = .zero } }
步骤2:修改viewWillTransition方法
把原来重复的逻辑替换成调用这个复用方法,代码会更简洁:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { [weak self] _ in self?.updateSelectedCellCenter() }) }
步骤3:修改didSelectItemAt方法
在点击Cell时,先调用这个方法更新center,再赋值给转场的start属性:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let detailViewController = storyboard?.instantiateViewController(withIdentifier: "TVC") as? ThirdViewController // 你的其他代码 // 先更新选中Cell的中心 updateSelectedCellCenter() transition.start = center print("outside center: \(center)") }
为什么不建议手动调用viewWillTransition?
viewWillTransition是UIViewController的核心生命周期方法之一,由系统在设备旋转前自动调用,它内部会触发一系列和布局、转场相关的逻辑。如果手动调用它,可能会导致:
- 重复触发布局更新,影响性能
- 干扰系统的旋转状态管理
- 引发其他依赖生命周期的逻辑出错
通过提取复用方法,我们既能保证逻辑的一致性,又能避免破坏系统的生命周期流程,是更安全、优雅的做法。
内容的提问来源于stack exchange,提问作者Coder221
相关产品推荐
相关产品推荐

