Swift中如何从collection view cell点击跳转至新的ViewController
问题根因
你无法调用self.storyboard的核心原因是:当前collectionView:didSelectItemAtIndexPath:方法所在的类不是UIViewController子类(大概率是你把collectionView的代理/datasource设置给了UITableViewCell子类、或者单独的代理管理对象),只有UIViewController实例才自带storyboard属性。
可行实现方案
方案1:用闭包/代理回调给VC1处理跳转(最推荐)
耦合度最低,符合分层设计逻辑:
- 给承载collectionView的UITableViewCell子类(或者你当前实现collectionView代理的类)定义点击回调
// 示例:TableViewCell子类中实现collectionView代理 class ContentTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource { // 回调可携带需要传给VC2的业务数据 var onCollectionCellTapped: ((_ selectedItem: Any?) -> Void)? func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let selectedData = yourDataSourceArray[indexPath.item] onCollectionCellTapped?(selectedData) } }
- 在VC1的tableView数据源方法中绑定回调,在VC1内部执行跳转
// VC1中的UITableViewDataSource实现 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ContentTableViewCell", for: indexPath) as! ContentTableViewCell // 绑定回调 cell.onCollectionCellTapped = { [weak self] selectedData in guard let self = self else { return } // 此处self为VC1实例,可正常调用storyboard let vc2 = self.storyboard?.instantiateViewController(withIdentifier: "VC2的StoryboardID") as! VC2 vc2.receiveData = selectedData // 按需选择跳转方式 self.navigationController?.pushViewController(vc2, animated: true) // self.present(vc2, animated: true) } return cell }
注意:需要提前在Storyboard中给VC2设置唯一的Storyboard ID
方案2:获取顶层VC直接执行跳转
适合轻量场景,不需要额外写回调逻辑:
// 在collectionView的didSelect方法中直接调用 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { // 直接通过Storyboard名称初始化VC2 let vc2 = UIStoryboard(name: "你的Storyboard文件名", bundle: nil).instantiateViewController(withIdentifier: "VC2的StoryboardID") as! VC2 // 获取当前App顶层VC执行跳转 if let topVC = UIApplication.shared.keyWindow?.rootViewController?.getTopmostVC() { topVC.navigationController?.pushViewController(vc2, animated: true) } } // 扩展UIViewController用于获取顶层VC extension UIViewController { func getTopmostVC() -> UIViewController { if let presentedVC = self.presentedViewController { return presentedVC.getTopmostVC() } if let navVC = self as? UINavigationController { return navVC.visibleViewController?.getTopmostVC() ?? navVC } if let tabVC = self as? UITabBarController { return tabVC.selectedViewController?.getTopmostVC() ?? tabVC } return self } }
方案3:代理直接绑定VC1
如果业务逻辑简单不需要拆分,可以直接把所有collectionView的dataSource、delegate设置给VC1,在VC1中实现collectionView的所有代理方法,此时didSelect方法中的self就是VC1实例,直接调用self.storyboard初始化VC2跳转即可。
内容的提问来源于stack exchange,提问作者Jawad Ali
相关产品推荐
相关产品推荐

