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

通过Protocol&Extension在MainScreenVC与RatesVC间传值崩溃求助

问题分析与解决方案

看起来你遇到的崩溃和数据传递失败,主要是两个关键问题导致的:

1. 协议参数类型不匹配+不安全传递

你的transferNameOfCurrency协议要求方法参数是String类型,但在MainScreenVC里,你直接传递了可选类型String?的nameOfTheCurrency。虽然你手动赋值为"EUR",但如果这个值意外为nil,直接传递会触发崩溃;而且严格来说这属于类型不匹配,编译器其实应该给你报错才对。

2. Delegate绑定到了错误的实例

在RatesVC的viewDidLoad里,你实例化了一个全新的MainScreenVC对象,然后给这个新对象设置delegate。但这个新对象根本不是你界面上实际显示的那个MainScreenVC!真正显示的MainScreenVC的transferCurrencyDelegate仍然是nil,所以当你调用transferCurrencyDelegate?.currencySelected(...)时,不仅回调不会触发,还可能因为参数类型问题直接崩溃。


修正后的完整代码

第一步:修复MainScreenVC的参数传递

import UIKit

// 建议规范协议命名,加上AnyObject限制类遵守,避免循环引用
protocol CurrencyTransferDelegate: AnyObject {
    func currencySelected(nameOfCurrency: String)
}

class MainScreenVC: UIViewController {
    // 用weak修饰delegate,防止内存泄漏
    weak var transferCurrencyDelegate: CurrencyTransferDelegate?
    var nameOfTheCurrency: String?

    @IBAction func updateRates(_ sender: Any) {
        nameOfTheCurrency = "EUR"
        // 安全解包后再传递参数,避免nil崩溃
        if let currencyName = nameOfTheCurrency {
            transferCurrencyDelegate?.currencySelected(nameOfCurrency: currencyName)
        }
        print(nameOfTheCurrency ?? "未获取到货币名称")
    }
}

第二步:正确绑定Delegate到实际显示的MainScreenVC

假设你的导航流程是从RatesVC跳转到MainScreenVC,那么在跳转时给实际要显示的MainScreenVC设置delegate,而不是在viewDidLoad里实例化新对象:

import UIKit

class RatesVC: UIViewController {
    var currencySelected: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        // 删除原来错误的实例化代码,保留必要的初始化逻辑
    }

    // 示例:处理跳转到MainScreenVC的按钮点击事件
    @IBAction func navigateToMainScreen(_ sender: Any) {
        if let mainVC = storyboard?.instantiateViewController(withIdentifier: "MainScreenVC") as? MainScreenVC {
            // 给即将显示的MainScreenVC设置delegate为当前RatesVC实例
            mainVC.transferCurrencyDelegate = self
            navigationController?.pushViewController(mainVC, animated: true)
        }
    }
}

extension RatesVC: CurrencyTransferDelegate {
    func currencySelected(nameOfCurrency: String) {
        currencySelected = nameOfCurrency
        print("收到传递的货币名称:\(currencySelected ?? "nil")")
    }
}

为什么这样能解决问题?

  1. 安全的参数传递:用可选绑定确保传递的是确定的String类型,避免了nil导致的崩溃;
  2. 正确的Delegate绑定:给实际要显示的MainScreenVC实例设置delegate,确保当updateRates触发时,RatesVC能收到回调并获取数据;
  3. 内存安全:给delegate加上weak修饰符,避免了两个VC互相引用导致的内存泄漏问题。

内容的提问来源于stack exchange,提问作者Ula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:12:23