同一UIViewController中第二个UICollectionView无法加载求助
看了你的代码和调试发现的问题,核心错误出在numberOfItemsInSection的判断逻辑上——你搞错了判断的对象!
问题根源
你在判断时用的是self.collectionView.tag == 1,但这个self.collectionView是你第一个集合视图的实例,不管当前回调的是哪个CollectionView,你都在检查第一个的标签,自然永远只会进入if分支。如果collectionViewBanner发起回调,你还是返回dataSource.count,要是dataSource为空就直接返回0,导致collectionViewBanner显示空白;就算dataSource有数据,后续cellForItemAt里又会用dataBanner的内容,很可能出现数组越界或显示错乱。
分步修复方案
修正
numberOfItemsInSection的判断逻辑
要使用方法参数里传入的collectionView来判断,这才是当前正在请求数据的那个集合视图:func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if collectionView.tag == 1 { return self.dataSource.count } else if collectionView.tag == 2 { return self.dataBanner.count } return 0 }确保两个CollectionView设置了对应Tag
打开你的Storyboard/XIB:- 选中第一个
collectionView,在右侧Attributes Inspector里把Tag设为1 - 选中
collectionViewBanner,把Tag设为2
(Tag值可以自定义,只要和代码里的判断一致就行)
- 选中第一个
验证数据源与代理的连接
防止Storyboard里的连接遗漏,建议在viewDidLoad里手动设置:override func viewDidLoad() { super.viewDidLoad() // 手动绑定数据源和代理 collectionView.dataSource = self collectionViewBanner.dataSource = self // 原有请求代码 getBanner { (data) in DispatchQueue.main.async { self.dataBanner = data self.collectionViewBanner.reloadData() } } getAudiobooksAPI { (data) in DispatchQueue.main.async { self.dataSource = data self.collectionView.reloadData() } } }优化Cell复用的判断逻辑(可选但更严谨)
你原来用实例对比collectionView == self.collectionView是可行的,但结合Tag判断会更清晰,同时建议给Banner创建独立的Cell子类(避免控件引用错误):func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if collectionView.tag == 1 { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell let content = self.dataSource[indexPath.item] cell.bookLabel.text = content.descricao cell.bookImage.setImage(url: content.urlImagem, placeholder: "") return cell } else if collectionView.tag == 2 { // 假设Banner有专门的Cell类CollectionViewBannerCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCellBanner", for: indexPath) as! CollectionViewBannerCell let content = self.dataBanner[indexPath.item] cell.bannerImage.setImage(url: content.urlImagem, placeholder: "") return cell } // 未知的CollectionView,抛出错误便于调试 fatalError("Received callback from unknown UICollectionView") }
额外提醒
你在cellForItemAt里给Banner Cell转换的是CollectionViewCell,如果Banner的Cell布局和普通Cell不一样,一定要创建独立的Cell子类,避免出现控件找不到或布局错乱的问题。
内容的提问来源于stack exchange,提问作者Bruno Vavretchek

