Swift4协议与代理回调实现困惑,求解决方案及代码示例
用协议代理实现VCB回调VCA的完整示例
没问题,我来帮你搞定这个Swift 4里的代理回调问题,直接上可运行的代码示例,每一步都给你讲清楚~
第一步:定义回调协议
我们先创建一个协议,用来规范VCB需要通知VCA执行的操作。这个协议可以放在VCB的.swift文件顶部,或者单独的文件里,这里为了方便放在VCB里:
import UIKit // 定义回调协议,继承AnyObject才能让代理用weak修饰 protocol VCBToVCADelegate: AnyObject { // 协议方法:通知VCA刷新表格 func refreshTableView() } class VCB: UIViewController { // 定义代理属性,必须用weak避免循环引用(VCA持有VCB,若代理为strong会导致双向持有内存泄漏) weak var delegate: VCBToVCADelegate? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white // 添加操作按钮 let actionButton = UIButton(type: .system) actionButton.setTitle("返回并刷新列表", for: .normal) actionButton.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside) actionButton.frame = CGRect(x: 80, y: 200, width: 250, height: 50) view.addSubview(actionButton) } @objc func actionButtonTapped() { // 1. 先调用代理方法,通知VCA刷新表格 delegate?.refreshTableView() // 2. 再pop回VCA navigationController?.popViewController(animated: true) } }
第二步:让VCA遵守协议并实现代理方法
接下来处理VCA的代码,让它遵守我们定义的协议,实现刷新逻辑,同时在跳转到VCB时设置代理:
import UIKit class VCA: UIViewController, UITableViewDataSource, UITableViewDelegate, VCBToVCADelegate { let tableView = UITableView() // 模拟数据源,点击VCB按钮后可以修改这个数组测试刷新效果 var dataList = ["第一条数据", "第二条数据", "第三条数据"] override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white title = "列表页面" // 配置tableView tableView.frame = view.bounds tableView.dataSource = self tableView.delegate = self tableView.register(UITableViewCell.self, forCellReuseIdentifier: "defaultCell") view.addSubview(tableView) } // MARK: - UITableView数据源方法 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "defaultCell", for: indexPath) cell.textLabel?.text = dataList[indexPath.row] return cell } // MARK: - UITableView代理方法(处理cell点击跳转) func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let vcB = VCB() // 关键步骤:设置VCB的代理为当前VCA vcB.delegate = self navigationController?.pushViewController(vcB, animated: true) } // MARK: - VCBToVCADelegate代理方法实现 func refreshTableView() { // 这里可以更新数据源,比如新增一条数据 dataList.append("新增数据\(dataList.count + 1)") // 刷新表格 tableView.reloadData() } }
你可能踩过的坑(划重点!)
- 忘记设置代理:很多时候回调失败都是因为跳转到VCB时没写
vcB.delegate = self,这一步绝对不能漏! - 代理没加weak:如果代理属性不用
weak,VCA和VCB会互相持有,导致内存泄漏,甚至回调失效。Swift里类类型的代理必须继承AnyObject才能用weak修饰。 - 协议方法未实现:如果协议方法不是可选的(没加
@objc optional),一定要在VCA里实现,否则编译会报错。
这样操作下来,你点击VCA的cell跳转到VCB,再点击VCB的按钮,就会先刷新VCA的表格,然后自动返回VCA啦~
内容的提问来源于stack exchange,提问作者tolerate_Me_Thx
相关产品推荐
相关产品推荐

