indexPathForPreferredFocusedView未被调用?设置remembersLastFocusedIndexPath为false仍无效
indexPathForPreferredFocusedView 未调用的问题 我之前做tvOS项目时也碰到过一模一样的问题,咱们一步步拆解可能的原因和解决办法:
先确认代理是否正确绑定
你得确保你的UIViewController已经成为UICollectionView的delegate。在viewDidLoad里一定要加上这句代码:collectionView.delegate = self同时记得让你的ViewController显式遵守
UICollectionViewDelegate协议(虽然Swift现在支持隐式遵守,但显式声明能避免不少隐性问题)。检查collectionView的可聚焦状态
系统只会对isFocusable为true的视图处理焦点逻辑。默认情况下UICollectionView的这个属性是true,但如果不小心被修改成false,就会直接跳过焦点相关的代理方法。你可以在调试的时候打印一下collectionView.isFocusable的值确认。排查是否有更高优先级的可聚焦视图
如果你的ViewController里还有其他可聚焦的视图(比如另一个UICollectionView、UIButton或者自定义的可聚焦视图),系统会优先选择这些视图作为焦点目标,导致你的collectionView的代理方法根本不会触发。
解决办法是重写ViewController的preferredFocusEnvironments方法,明确指定collectionView为优先聚焦的环境:override var preferredFocusEnvironments: [UIFocusEnvironment] { return [collectionView] }确认collectionView有可聚焦的cell
如果collectionView当前没有加载任何cell(比如数据源为空,或者还没执行reloadData()),系统自然不会调用indexPathForPreferredFocusedView(in:)——因为没有可聚焦的目标。你可以在调试时检查collectionView.numberOfItems(inSection: 0)的返回值,确保大于0,并且已经完成了数据加载和reload。尝试强制触发焦点更新
某些情况下,系统的焦点状态可能没有及时刷新,即使你设置了remembersLastFocusedIndexPath = false也不会触发代理方法。你可以在viewDidAppear(_:)里手动触发焦点更新:override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) collectionView.setNeedsFocusUpdate() collectionView.updateFocusIfNeeded() }
按照这个顺序排查下来,基本能解决大部分indexPathForPreferredFocusedView未调用的问题。
内容的提问来源于stack exchange,提问作者Aymen HARRATH

