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

如何在TableView内嵌CollectionView点击时调用ViewController方法刷新数据

嘿,这个场景我太熟悉了!要实现嵌套在TableViewCell里的CollectionViewCell点击后,触发父控制器OneStopShopVC的API调用并刷新第二个TableCell,有几种靠谱的方案,我给你一步步拆解:

方案一:代理模式(最推荐,解耦清晰,iOS组件通信标准玩法)

这是iOS开发中最常用的组件间通信方式,逻辑清晰,而且方便后续扩展,步骤如下:

  1. 给CategoryTableViewCell定义代理协议
    在CategoryTableViewCell.swift里创建一个协议,声明点击事件的方法:
import UIKit

// 定义代理协议,注意用AnyObject保证只能被类实现
protocol CategoryTableViewCellDelegate: AnyObject {
    // 可以根据需求传递参数,比如选中的分类数据、索引路径等
    func categoryCell(_ cell: CategoryTableViewCell, didSelectCategoryAt indexPath: IndexPath)
}

class CategoryTableViewCell: UITableViewCell {
    // 代理属性必须用weak,避免循环引用
    weak var delegate: CategoryTableViewCellDelegate?
    // 假设你已经有了CollectionView的数据源数组
    var categories: [YourCategoryModel] = []
    
    // MARK: - UICollectionViewDelegate
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // 调用代理方法,把点击事件传递出去
        delegate?.categoryCell(self, didSelectCategoryAt: indexPath)
    }
}
  1. 在OneStopShopVC中实现代理并设置
    在OneStopShopVC.swift里,先遵守代理协议,然后在创建cell的时候设置代理:
extension OneStopShopVC: CategoryTableViewCellDelegate {
    func categoryCell(_ cell: CategoryTableViewCell, didSelectCategoryAt indexPath: IndexPath) {
        // 这里可以拿到选中的分类数据(如果需要)
        let selectedCategory = cell.categories[indexPath.item]
        
        // 调用你的API方法
        searchDataFromFilteredApi()
        
        // API请求完成后,刷新第二个TableCell(假设它在section 0的row 1位置)
        // 局部刷新比全局reloadData()更高效
        tableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
    }
}

// 在tableView的cellForRowAt方法里设置代理
extension OneStopShopVC: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryTableViewCell", for: indexPath) as! CategoryTableViewCell
            // 设置代理为当前VC
            cell.delegate = self
            // 配置cell的数据源
            cell.categories = yourCategoryDataArray
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: "DataTableCell", for: indexPath) as! DataTableCell
            // 用API返回的数据配置第二个cell
            cell.configure(with: yourApiResponseData)
            return cell
        }
    }
}

方案二:闭包(简洁直观,适合简单场景)

如果不想写代理协议,闭包是更轻量化的选择,代码更紧凑:

  1. 在CategoryTableViewCell里定义闭包属性
class CategoryTableViewCell: UITableViewCell {
    // 定义闭包类型,参数可以根据需求调整
    var onCategorySelected: ((IndexPath) -> Void)?
    var categories: [YourCategoryModel] = []
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // 调用闭包,传递点击信息
        onCategorySelected?(indexPath)
    }
}
  1. 在OneStopShopVC中绑定闭包
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryTableViewCell", for: indexPath) as! CategoryTableViewCell
        cell.categories = yourCategoryDataArray
        // 绑定闭包,注意用[weak self]避免循环引用
        cell.onCategorySelected = { [weak self] indexPath in
            guard let self = self else { return }
            let selectedCategory = cell.categories[indexPath.item]
            self.searchDataFromFilteredApi()
            self.tableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
        }
        return cell
    } else {
        // 配置第二个cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "DataTableCell", for: indexPath) as! DataTableCell
        cell.configure(with: yourApiResponseData)
        return cell
    }
}

方案三:通知中心(适合跨多层级,但尽量少用)

如果你的组件层级特别深,或者临时需要快速实现,可以用通知中心,但缺点是代码耦合度高,不好维护,容易出现通知满天飞的情况:

  1. 在OneStopShopVC中注册通知观察者
override func viewDidLoad() {
    super.viewDidLoad()
    // 注册通知,监听分类选中事件
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleCategorySelected),
        name: NSNotification.Name("CategorySelected"),
        object: nil
    )
}

@objc private func handleCategorySelected(notification: Notification) {
    // 从通知的userInfo里获取数据(如果需要)
    if let indexPath = notification.userInfo?["indexPath"] as? IndexPath {
        // 调用API并刷新cell
        searchDataFromFilteredApi()
        tableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
    }
}

// 记得在页面消失时移除观察者,避免内存泄漏
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}
  1. 在CategoryTableViewCell中发送通知
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    // 发送通知,携带需要的数据
    NotificationCenter.default.post(
        name: NSNotification.Name("CategorySelected"),
        object: nil,
        userInfo: ["indexPath": indexPath]
    )
}

最后说句心里话

个人最推荐代理模式,因为它的代码结构清晰,适合组件复用,后续扩展也方便;闭包适合简单的小型场景,代码更简洁;通知中心尽量少用,除非是跨多个层级的全局事件,不然很容易让代码变得难以维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:50:46