CollectionView跳转Segue后目标ViewController对象为nil问题排查
问题分析与解决方案
哦,这个问题我之前也踩过坑!你这里犯了一个非常典型的错误——你同时混用了两种ViewController跳转方式,导致你赋值的AdViewPageVC实例根本不是实际跳转到的那个。
错误原因拆解
你看,你的代码里先手动实例化了adViewVC并给advertisement赋值,但紧接着又调用了performSegue(withIdentifier:...)。而系统执行Segue的时候,会完全按照Storyboard里的配置重新创建一个AdViewPageVC实例,和你之前手动创建的那个是完全独立的两个对象!所以你之前的赋值操作等于白做,目标VC里的advertisement自然就是nil了。
两种正确的解决方法
方法一:用Segue的prepare(for:sender:)传递数据
这是Storyboard Segue跳转的标准数据传递方式,把数据通过sender参数传递,然后在prepare方法里给目标VC赋值:
// 修改didSelectItemAt方法,只触发Segue并传递选中的数据 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let selectedAd = adArray[indexPath.row] performSegue(withIdentifier: adViewPageSegue, sender: selectedAd) } // 实现prepare方法,在这里完成数据传递 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // 先判断Segue标识符是否匹配 guard segue.identifier == adViewPageSegue else { return } // 把目标VC转换成我们需要的类型 guard let adViewVC = segue.destination as? AdViewPageVC else { return } // 从sender里取出之前传递的广告数据,赋值给目标VC adViewVC.advertisement = sender as? Advertisement }
方法二:直接手动跳转(放弃Segue)
如果不想用Storyboard的Segue,也可以直接手动实例化VC并跳转,这样赋值的就是实际展示的那个实例:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let adViewVC = storyboard?.instantiateViewController(withIdentifier: adViewPageID) as? AdViewPageVC else { return } let selectedAd = adArray[indexPath.row] adViewVC.advertisement = selectedAd // 根据你的导航结构选择跳转方式: // 如果是导航控制器管理的页面,用push navigationController?.pushViewController(adViewVC, animated: true) // 如果是模态展示,用present // present(adViewVC, animated: true) }
额外注意事项
- 确保
adViewPageSegue和adViewPageID这两个标识符,和你Storyboard里设置的完全一致(大小写、拼写都不能错) - 确认
AdViewPageVC的类名已经正确关联到Storyboard里的ViewController上
内容的提问来源于stack exchange,提问作者A. Petrizza
相关产品推荐
相关产品推荐

