Swift中无法从UICollectionView传值至新ViewController的问题
UICollectionView通过Segue传值的正确方式
为什么UICollectionView没有indexPathForSelectedRow?
UITableView默认是单选模式,所以提供了indexPathForSelectedRow直接获取选中行的索引;而UICollectionView原生支持多选,因此设计上用indexPathsForSelectedItems(返回[IndexPath]?)来获取所有选中项的索引数组,单选场景下取第一个元素即可。
你之前的代码为什么会返回nil?
你尝试把sender转成IndexPath但得到nil,核心原因是segue的触发方式决定了sender的类型:
- 如果是从UICollectionViewCell直接连线触发的segue,
sender实际是被点击的UICollectionViewCell实例,不是IndexPath,强转自然会失败。 - 如果是手动调用
performSegue(withIdentifier:sender:)触发,若没主动传入IndexPath,sender也不会是索引对象。
正确的传值方案
方案1:通过indexPathsForSelectedItems获取选中项(适合手动触发segue)
如果是通过按钮等手动触发segue,且确保是单选场景,可以直接从collectionView获取选中的索引:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.destination is PlacesViewController else { return } // 获取第一个选中的索引(单选场景) guard let selectedIndexPath = collectionView.indexPathsForSelectedItems?.first else { return } let selectedPlace = places[selectedIndexPath.row] let targetVC = segue.destination as! PlacesViewController targetVC.named = selectedPlace.name as String }
方案2:通过sender(cell)反向获取索引(适合cell触发的segue)
如果segue是直接从UICollectionViewCell连线到目标VC,通过cell实例反向获取对应的IndexPath:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.destination is PlacesViewController else { return } // 从sender拿到点击的cell,再获取索引 guard let tappedCell = sender as? UICollectionViewCell, let selectedIndexPath = collectionView.indexPath(for: tappedCell) else { return } let selectedPlace = places[selectedIndexPath.row] let targetVC = segue.destination as! PlacesViewController targetVC.named = selectedPlace.name as String }
方案3:手动触发segue时主动传入IndexPath
如果是在collectionView(_:didSelectItemAt:)方法里手动触发segue,可以直接把IndexPath作为sender传入:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { performSegue(withIdentifier: "YourSegueIdentifier", sender: indexPath) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.destination is PlacesViewController else { return } // 此时sender就是传入的IndexPath guard let selectedIndexPath = sender as? IndexPath else { return } let selectedPlace = places[selectedIndexPath.row] let targetVC = segue.destination as! PlacesViewController targetVC.named = selectedPlace.name as String }
内容的提问来源于stack exchange,提问作者mystic cola
相关产品推荐
相关产品推荐

