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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:21:28