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

如何将ChildVC的计数器数据回传至MainVC对应的CollectionView Cell

嘿,这个需求在iOS开发里挺常见的,咱们用代理模式或者闭包回调都能轻松实现,我给你拆解两种方案,你挑顺手的来就行~

方案一:代理模式(传统iOS回调方式)

这种方式很规范,适合稍微复杂一点的交互场景,步骤如下:

  1. 先在ChildVC里定义代理协议,声明数据回传的方法
// ChildVC.swift
protocol ChildVCDelegate: AnyObject {
    // 参数包含选中数量和对应Cell的索引,方便MainVC定位更新
    func didUpdateSelectedCount(_ count: Int, forCellIndex index: Int)
}

class ChildVC: UIViewController {
    // 代理属性必须用weak,避免循环引用
    weak var delegate: ChildVCDelegate?
    // 记录当前是从哪个Cell跳过来的
    var currentCellIndex: Int = 0
    // 你的计数器变量,监听变化更新界面
    var selectedCount: Int = 0 {
        didSet {
            countLabel.text = "\(selectedCount) selected"
        }
    }
    
    // 假设用户点击确认按钮完成选择,触发回传
    @IBAction func confirmBtnTapped(_ sender: UIButton) {
        // 通过代理把数据传给MainVC
        delegate?.didUpdateSelectedCount(selectedCount, forCellIndex: currentCellIndex)
        // 关闭ChildVC(如果是push进来的就用popViewController)
        dismiss(animated: true)
    }
}
  1. 在MainVC里遵守代理协议,实现回传逻辑并更新Cell
// MainVC.swift
class MainVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, ChildVCDelegate {
    // 存储每个Cell的选中数量,初始全为0
    private var cellSelectedCounts: [Int] = Array(repeating: 0, count: 5)
    
    // 跳转Segue前,给ChildVC传索引并设置代理
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard segue.identifier == "ToChildVC", // 记得给Segue设置这个唯一标识
              let childVC = segue.destination as? ChildVC,
              let selectedCell = sender as? UICollectionViewCell,
              let indexPath = collectionView.indexPath(for: selectedCell) else {
            return
        }
        // 把当前Cell的索引传给ChildVC
        childVC.currentCellIndex = indexPath.item
        // 设置代理
        childVC.delegate = self
        // 把当前Cell已有的计数传给ChildVC,进去就能显示之前的选择
        childVC.selectedCount = cellSelectedCounts[indexPath.item]
    }
    
    // 实现代理方法,更新对应Cell的计数并刷新界面
    func didUpdateSelectedCount(_ count: Int, forCellIndex index: Int) {
        cellSelectedCounts[index] = count
        // 只刷新对应的Cell,比全量刷新更高效
        collectionView.reloadItems(at: [IndexPath(item: index, section: 0)])
    }
    
    // CollectionView数据源方法,给Cell设置标签文本
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellID", for: indexPath) as! YourCustomCell
        cell.countLabel.text = "\(cellSelectedCounts[indexPath.item]) selected"
        return cell
    }
}

方案二:闭包回调(更简洁的方式)

如果你的交互逻辑比较简单,闭包写法会更清爽,不用额外写协议:

  1. 在ChildVC里定义回调闭包
// ChildVC.swift
class ChildVC: UIViewController {
    var currentCellIndex: Int = 0
    var selectedCount: Int = 0 {
        didSet {
            countLabel.text = "\(selectedCount) selected"
        }
    }
    // 定义回调闭包,@escaping表示闭包会在VC生命周期外执行
    var updateCountCallback: ((Int, Int) -> Void)?
    
    @IBAction func confirmBtnTapped(_ sender: UIButton) {
        // 执行闭包回传数据
        updateCountCallback?(selectedCount, currentCellIndex)
        dismiss(animated: true)
    }
}
  1. 在MainVC的Segue准备阶段设置闭包
// MainVC.swift
class MainVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
    private var cellSelectedCounts: [Int] = Array(repeating: 0, count: 5)
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard segue.identifier == "ToChildVC",
              let childVC = segue.destination as? ChildVC,
              let selectedCell = sender as? UICollectionViewCell,
              let indexPath = collectionView.indexPath(for: selectedCell) else {
            return
        }
        childVC.currentCellIndex = indexPath.item
        childVC.selectedCount = cellSelectedCounts[indexPath.item]
        // 设置闭包,用[weak self]避免循环引用
        childVC.updateCountCallback = { [weak self] count, index in
            guard let self = self else { return }
            self.cellSelectedCounts[index] = count
            self.collectionView.reloadItems(at: [IndexPath(item: index, section: 0)])
        }
    }
    
    // 同样的Cell数据源方法,设置标签文本
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellID", for: indexPath) as! YourCustomCell
        cell.countLabel.text = "\(cellSelectedCounts[indexPath.item]) selected"
        return cell
    }
}

注意事项

  • 一定要给Storyboard里的Segue设置唯一的identifier(比如示例里的ToChildVC),不然prepare(for:sender:)里识别不了跳转
  • 如果ChildVC是通过push方式跳转的,关闭时要换成navigationController?.popViewController(animated: true)
  • 闭包里记得用[weak self],防止循环引用导致内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:43:31