You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将UITableViewCell内嵌套UICollectionViewCell的数据传递到其他ViewController

报错原因及修复方案

核心错误点

  • 数组越界隐患:namearr仅包含5个元素,但collectionView数据源返回10个item,点击下标≥5的cell会直接崩溃
  • 控件提前赋值失效:DetailViewController刚实例化时,img等IBOutlet控件还未加载完成,直接给vc?.img.image赋值会无效甚至崩溃
  • 导航控制器调用错误:UITableViewCell没有navigationController属性,在cell内执行跳转逻辑本身就不符合规范,也会直接报错
  • 可能的Storyboard实例化错误:需要确认DetailViewController所在的Storyboard文件名是否确实为DetailViewController,默认项目中所有界面通常放在Main.storyboard中,名称填错会导致vc实例化失败

修复代码示例

1. 修正ExploreTableViewCell代码

添加回调闭包把点击事件和数据传递到上层ViewController,不要在cell内处理跳转

import UIKit

class ExploreTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{

    @IBOutlet var collectionView: UICollectionView!
    // 定义回调闭包,把点击的图片名传递出去
    var onItemClick: ((String) -> Void)?
    var namearr = ["images-1", "images-2", "images-3", "images-4", "images-5"]

    override func awakeFromNib() {
        super.awakeFromNib()
        collectionView.delegate = self
        collectionView.dataSource = self
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // 修复数组越界,返回数组实际元素数量
        return namearr.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        // 这里给cell里的图片和标签赋值,按照你实际的控件tag或者自定义cell属性修改即可
        if let imgView = cell.viewWithTag(100) as? UIImageView {
            imgView.image = UIImage(named: namearr[indexPath.row])
        }
        if let label = cell.viewWithTag(101) as? UILabel {
            label.text = namearr[indexPath.row]
        }
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 132, height: 134)
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // 点击时触发回调,把图片名传出去
        onItemClick?(namearr[indexPath.row])
    }
}

2. 修正DetailViewController代码

新增接收数据的存储属性,等界面加载完成后再给控件赋值

import UIKit

class DetailViewController: UIViewController {
    @IBOutlet weak var img: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    // 新增接收参数的属性,不要直接赋值IBOutlet
    var receiveImageName: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 界面加载完成后再给控件赋值
        if let imgName = receiveImageName {
            img.image = UIImage(named: imgName)
            nameLabel.text = imgName
        }
    }
}

3. 在使用ExploreTableViewCell的宿主ViewController中处理跳转

在你显示这个TableView的VC的tableView(_:cellForRowAt:)方法里添加回调监听,执行跳转逻辑

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ExploreTableViewCell", for: indexPath) as! ExploreTableViewCell
    // 监听cell的点击回调
    cell.onItemClick = { [weak self] imageName in
        guard let self = self else { return }
        // 实例化DetailViewController,注意Storyboard名称要和你实际的一致
        guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController else {
            return
        }
        // 传递参数
        vc.receiveImageName = imageName
        // 跳转
        self.navigationController?.pushViewController(vc, animated: true)
    }
    return cell
}

内容的提问来源于stack exchange,提问作者JESTIN SAJI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:06:02