Swift中点击按钮实现不同ViewController的TableViewCell数据传递
解决思路与代码实现
首先明确:你要的是点击Cell内按钮触发数据传递,而非点击整个Cell(didSelectRowAt是点击Cell整体的回调),先把这两个触发场景区分开,再看具体实现。
一、Closure 实现方式(推荐)
1. 自定义源Cell(SourceCell)
给Cell内的按钮绑定点击事件,定义Closure用于向外传递数据:
import UIKit class SourceCell: UITableViewCell { // 假设Cell展示的数据模型 var dataModel: String? { didSet { textLabel?.text = dataModel } } // 定义Closure,用于传递数据 var onButtonTap: ((String) -> Void)? // 按钮点击事件 @IBAction func tapTransferButton(_ sender: UIButton) { guard let data = dataModel else { return } onButtonTap?(data) // 触发Closure,传递数据 } }
2. 源ViewController(SourceVC)
在cellForRowAt中绑定Closure,接收Cell传递的数据后,跳转到目标VC并传值:
class SourceVC: UIViewController, UITableViewDataSource { let dataList = ["数据1", "数据2", "数据3"] func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SourceCell", for: indexPath) as! SourceCell cell.dataModel = dataList[indexPath.row] // 绑定Closure cell.onButtonTap = { [weak self] transferredData in // 初始化目标VC,传递数据 let targetVC = TargetVC() targetVC.receivedData = transferredData // 跳转(根据你的导航方式调整,比如push或present) self?.navigationController?.pushViewController(targetVC, animated: true) } return cell } }
3. 目标ViewController(TargetVC)
接收数据并刷新自己的TableView:
class TargetVC: UIViewController, UITableViewDataSource { var receivedData: String? // 目标VC的数据源,这里把接收的数据加入列表 var targetDataList = [String]() override func viewDidLoad() { super.viewDidLoad() if let data = receivedData { targetDataList.append(data) tableView.reloadData() // 刷新TableView } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return targetDataList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "TargetCell", for: indexPath) cell.textLabel?.text = targetDataList[indexPath.row] return cell } }
二、Delegate 实现方式
1. 定义Delegate协议
protocol SourceCellDelegate: AnyObject { func sourceCell(_ cell: SourceCell, didTapTransferButtonWith data: String) }
2. 修改SourceCell
添加Delegate属性,按钮点击时调用Delegate方法:
class SourceCell: UITableViewCell { weak var delegate: SourceCellDelegate? var dataModel: String? { didSet { textLabel?.text = dataModel } } @IBAction func tapTransferButton(_ sender: UIButton) { guard let data = dataModel else { return } delegate?.sourceCell(self, didTapTransferButtonWith: data) } }
3. SourceVC 遵守并实现Delegate
class SourceVC: UIViewController, UITableViewDataSource, SourceCellDelegate { let dataList = ["数据1", "数据2", "数据3"] func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SourceCell", for: indexPath) as! SourceCell cell.dataModel = dataList[indexPath.row] cell.delegate = self // 设置Delegate return cell } // 实现Delegate方法 func sourceCell(_ cell: SourceCell, didTapTransferButtonWith data: String) { let targetVC = TargetVC() targetVC.receivedData = data navigationController?.pushViewController(targetVC, animated: true) } // 其余UITableViewDataSource方法同前 }
三、关于didSelectRowAt的困惑
tableView(_:didSelectRowAt:)是用户点击整个TableViewCell区域时触发的回调,和Cell内按钮的点击事件是两个独立的触发逻辑。- 如果你的需求是点击Cell整体就传值,那把传值逻辑写在这个方法里即可:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let selectedData = dataList[indexPath.row] let targetVC = TargetVC() targetVC.receivedData = selectedData navigationController?.pushViewController(targetVC, animated: true) tableView.deselectRow(at: indexPath, animated: true) // 可选:取消Cell选中状态 }
- 如果你是点击Cell内按钮,这个方法不会自动执行,不用在里面写逻辑。
内容的提问来源于stack exchange,提问作者Sahil Sokhal
相关产品推荐
相关产品推荐

