UICollectionViewController跨控制器调用数据源方法异常求助
嘿,我帮你拆解下这个诡异的问题,从你的代码和现象来看,核心原因是两个UICollectionViewController共用了同一个UICollectionViewFlowLayout实例!这直接导致了delegate/dataSource的绑定混乱,才会出现第一个VC调用第二个VC方法的怪事。
问题根源详解
看你创建第二个VC的代码:
let commentController = searchMainViewController(collectionViewLayout: layout)
这里的layout是你创建第一个HomeController时初始化的同一个对象。而UICollectionViewFlowLayout内部会持有对应的collectionView和delegate引用,当两个CollectionView绑定到同一个布局实例时,切换Tab会让layout的delegate被覆盖,最终导致第一个VC的CollectionView“认错主人”,调用第二个VC的数据源方法,自然就加载不出单元格了。
分步修复方案
1. 为每个CollectionVC创建独立的Layout实例
修改第二个VC的创建代码,单独初始化一个新的UICollectionViewFlowLayout,让两个CollectionView各用各的布局:
// 第二个VC的创建代码 let commentLayout = UICollectionViewFlowLayout() // 新建独立的布局实例 let commentController = searchMainViewController(collectionViewLayout: commentLayout) let commentViewNavController = UINavigationController(rootViewController: commentController) // 后续tabBarItem的设置保持不变
2. 移除冗余的标签校验逻辑(可选但推荐)
解决了布局共用的问题后,你之前为了避免崩溃加的collectionView.tag判断就没必要了,可以把这些冗余代码删掉,让逻辑更清晰:
比如第一个VC的numberOfItemsInSection可以简化成:
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return videos.count }
3. 优化CollectionView的初始化时机
建议把注册cell、绑定delegate/dataSource的逻辑放在viewDidLoad里(而不是viewWillAppear),因为viewDidLoad只会执行一次,避免重复注册和绑定:
override func viewDidLoad() { super.viewDidLoad() setupCollectionView() } private func setupCollectionView(){ collectionView?.register(VideoCell.self, forCellWithReuseIdentifier: cellId) collectionView?.delegate = self collectionView?.dataSource = self // 这里可以添加layout的属性配置,比如itemSize、minimumLineSpacing等 }
额外优化建议
如果你的数据可能在后台更新,切换回第一个Tab时可以主动刷新CollectionView,确保数据最新:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) collectionView?.reloadData() }
按照上面的步骤修改后,应该就能彻底解决切换Tab后单元格消失、方法调用混乱的问题啦!
内容的提问来源于stack exchange,提问作者Akash More

