Swift 3:如何通过Segue实现C、D视图向B视图回传数据
嘿,这个场景我太熟悉了!在iOS开发里处理这种反向Segue传值,最常用也最稳妥的是委托模式,当然闭包也是个简洁的备选方案。我给你详细拆解两种实现方式,完美适配你C→B、D→B的回传需求:
方法一:委托模式(推荐,适合明确的页面间传值)
这种方式逻辑清晰,适合需要长期维护的项目,能明确页面间的传值契约。
步骤1:给C、D页面定义委托协议
分别在CViewController和DViewController顶部定义协议,约定回传数据的方法:
// CViewController.swift protocol CViewControllerDelegate: AnyObject { // 方法参数可以根据实际需求调整,比如只传email字符串 func cViewController(_ vc: CViewController, didSendBackData data: [String: Any]) } class CViewController: UIViewController { // 接收从B传来的email var email: String? // 委托对象用weak修饰,避免循环引用 weak var delegate: CViewControllerDelegate? // 假设触发回传的按钮点击事件 @IBAction func backToBAction(_ sender: UIButton) { // 准备要回传的数据(可以结合email或其他页面数据) let backData = ["email": email ?? "", "source": "C"] // 调用委托方法传递数据 delegate?.cViewController(self, didSendBackData: backData) // 返回B页面(如果是push跳转用pop,present跳转用dismiss) navigationController?.popViewController(animated: true) } }
// DViewController.swift protocol DViewControllerDelegate: AnyObject { func dViewController(_ vc: DViewController, didSendBackData data: [String: Any]) } class DViewController: UIViewController { var email: String? weak var delegate: DViewControllerDelegate? @IBAction func backToBAction(_ sender: UIButton) { let backData = ["email": email ?? "", "source": "D"] delegate?.dViewController(self, didSendBackData: backData) navigationController?.popViewController(animated: true) } }
步骤2:让B页面遵守协议并实现方法
在BViewController中,遵守C和D的委托协议,同时在跳转时设置委托对象:
// BViewController.swift class BViewController: UIViewController, CViewControllerDelegate, DViewControllerDelegate { var email: String? // 跳转前给目标页面传值+设置委托 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let targetVC = segue.destination as? CViewController { targetVC.email = self.email targetVC.delegate = self // 将B设置为C的委托 } else if let targetVC = segue.destination as? DViewController { targetVC.email = self.email targetVC.delegate = self // 将B设置为D的委托 } } // 实现C的委托方法,接收回传数据 func cViewController(_ vc: CViewController, didSendBackData data: [String: Any]) { if let email = data["email"] as? String, let source = data["source"] as? String { print("从C页面回传的email:\(email),来源:\(source)") // 这里可以更新B页面的UI或变量 self.email = email } } // 实现D的委托方法,接收回传数据 func dViewController(_ vc: DViewController, didSendBackData data: [String: Any]) { if let email = data["email"] as? String, let source = data["source"] as? String { print("从D页面回传的email:\(email),来源:\(source)") self.email = email } } }
方法二:闭包方式(更简洁,适合简单传值场景)
如果你的传值逻辑比较简单,闭包写法会更紧凑,不需要额外定义协议:
步骤1:给C、D页面定义闭包属性
// CViewController.swift class CViewController: UIViewController { var email: String? // 定义闭包,参数为回传的数据类型 var onBackToB: (([String: Any]) -> Void)? @IBAction func backToBAction(_ sender: UIButton) { let backData = ["email": email ?? "", "source": "C"] // 调用闭包传递数据 onBackToB?(backData) navigationController?.popViewController(animated: true) } }
// DViewController.swift class DViewController: UIViewController { var email: String? var onBackToB: (([String: Any]) -> Void)? @IBAction func backToBAction(_ sender: UIButton) { let backData = ["email": email ?? "", "source": "D"] onBackToB?(backData) navigationController?.popViewController(animated: true) } }
步骤2:在B页面跳转时设置闭包逻辑
// BViewController.swift class BViewController: UIViewController { var email: String? override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let targetVC = segue.destination as? CViewController { targetVC.email = self.email // 设置闭包,用[weak self]避免循环引用 targetVC.onBackToB = { [weak self] data in guard let self = self else { return } if let email = data["email"] as? String, let source = data["source"] as? String { print("从C页面回传的email:\(email),来源:\(source)") self.email = email } } } else if let targetVC = segue.destination as? DViewController { targetVC.email = self.email targetVC.onBackToB = { [weak self] data in guard let self = self else { return } if let email = data["email"] as? String, let source = data["source"] as? String { print("从D页面回传的email:\(email),来源:\(source)") self.email = email } } } } }
关键注意事项
- 无论是委托还是闭包,都要注意循环引用:委托用
weak修饰对象,闭包用[weak self]捕获弱引用,防止内存泄漏。 - 如果你的页面是用
present方式跳转的,返回时要替换为dismiss(animated: true),而不是popViewController。 - 数据类型可以根据实际需求调整,比如只需要回传email字符串,就把协议方法或闭包的参数改成
String类型,更简洁安全。
内容的提问来源于stack exchange,提问作者QuickAccount123
相关产品推荐
相关产品推荐

