点击导航栏返回按钮时如何更新TableView数据源?
兄弟,我懂你这种场景下的困惑!之前我也在类似的发票管理APP里踩过坑,给你整理几个亲测有效的方案,应该能帮你解决问题:
方案1:用Unwind Segue(最贴合你提到的场景)
你之前可能没摸透Unwind Segue的正确用法,它不是普通的跳转segue,而是专门用来从子VC回退到父VC时触发回调的。按这几步来:
- 在第一个VC(发票列表VC)里定义Unwind方法:
这个方法会在你从第三个VC回退回来时被调用,直接在这里更新数据源就行:@IBAction func unwindToInvoiceList(_ segue: UIStoryboardSegue) { // 先判断来源是不是支付完成的VC if let paymentDoneVC = segue.source as? PaymentCompletionVC { // 如果支付成功(假设第三个VC有个isPaymentSuccess的属性) if paymentDoneVC.isPaymentSuccess { // 更新数据源——要么重新从服务器拉最新的发票列表,要么修改本地数组 self.invoices = self.getUpdatedInvoiceList() // 刷新TableView self.tableView.reloadData() } } } - 在Storyboard里绑定Unwind Segue:
找到第三个VC的“支付完成”按钮,按住Ctrl拖线到VC顶部的「Exit」图标(就是那个绿色的出口箭头),然后选择你刚才定义的unwindToInvoiceList:方法。这样点击支付按钮后,会自动回退到第一个VC,同时触发上面的更新逻辑。
方案2:闭包回调(灵活度拉满,代码可控)
如果不想依赖Storyboard的Segue,闭包是iOS开发里传递回调的常用操作,步骤也清晰:
- 在第二个VC(发票详情VC)里定义闭包属性:
这个闭包用来通知第一个VC“支付完成了,该更新数据了”:// 用可选类型,避免没设置时崩溃 var onPaymentFinished: (() -> Void)? - 在第三个VC支付完成后触发闭包:
当第三个VC处理完支付,关闭自己的时候,通知第二个VC,再由第二个VC触发闭包:@IBAction func confirmPaymentTapped(_ sender: UIButton) { // 先处理支付逻辑(比如调用接口、更新本地状态) // 关闭当前VC dismiss(animated: true) { // 找到上层的详情VC,触发闭包 if let detailVC = self.presentingViewController as? InvoiceDetailVC { detailVC.onPaymentFinished?() } } } - 在第一个VC跳转到详情VC时,设置闭包内容:
在第一个VC的prepare(for:sender:)方法里,给详情VC的闭包赋值,指定支付完成后要做的事:override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let detailVC = segue.destination as? InvoiceDetailVC { // 用weak self避免循环引用 detailVC.onPaymentFinished = { [weak self] in guard let self = self else { return } // 更新数据源+刷新TableView self.invoices = self.getUpdatedInvoiceList() self.tableView.reloadData() } } }
方案3:通知中心(适合跨多层VC的复杂场景)
如果你的VC层级更多,或者需要多个地方响应支付完成的事件,通知中心是个不错的选择:
- 在第一个VC里注册通知观察者:
要记得在VC消失时移除观察者,避免内存泄漏:override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 注册通知,名字随便取,只要前后一致就行 NotificationCenter.default.addObserver( self, selector: #selector(updateInvoiceList), name: NSNotification.Name("PaymentCompleted"), object: nil ) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 移除观察者 NotificationCenter.default.removeObserver(self) } @objc private func updateInvoiceList() { // 更新数据源+刷新TableView self.invoices = self.getUpdatedInvoiceList() self.tableView.reloadData() } - 在第三个VC支付完成后发送通知:
@IBAction func confirmPaymentTapped(_ sender: UIButton) { // 处理支付逻辑 dismiss(animated: true) { // 发送通知,告诉所有观察者“支付完成了” NotificationCenter.default.post( name: NSNotification.Name("PaymentCompleted"), object: nil ) } }
个人更推荐你用方案1或者方案2,因为逻辑更直观,代码耦合度低;通知中心适合更复杂的场景,但要小心内存泄漏的问题。
内容的提问来源于stack exchange,提问作者Renan Aguiar
相关产品推荐
相关产品推荐

