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

iOS开发问题:无法从BarCodeScannerViewController向TableViewController回传数据

解决从BarCodeScannerViewController向TableViewController回传数据的问题

看起来你遇到的核心问题是回传数据时赋值未生效,导致TableViewController里的BarCode始终是初始空值。我们先拆解现有代码的问题,再给出两种可靠的iOS常用解决方案。

问题分析

你当前通过presentingViewController as? TableViewController获取目标VC实例的方式存在潜在风险:

  • 如果你的TableViewController被包裹在UINavigationController中,presentingViewController实际指向的是导航控制器而非TableViewController本身,强转会失败,presenter为nil,自然无法完成赋值。
  • 即使强转成功,dismiss操作会立即销毁SecondVC,可能存在赋值时机滞后的问题(比如TableViewController的viewWillAppear在dismiss后执行,但赋值还未同步)。

解决方案1:闭包回调(推荐,代码更简洁灵活)

这种方式不依赖VC层级关系,直接通过闭包传递数据,耦合度更低。

步骤1:在SecondVC中定义闭包

class BarCodeScannerViewController: UIViewController {
    // 定义接收扫描结果的闭包
    var onBarCodeReceived: ((String) -> Void)?
    
    @objc func SendDataBack(_ button: UIBarButtonItem!) {
        // 调用闭包传递数据
        onBarCodeReceived?("Test")
        self.dismiss(animated: true, completion: nil)
    }
}

步骤2:在FirstVC中绑定闭包

当你present扫描VC时,提前设置闭包逻辑:

// 假设你是这样弹出扫描页面的
func showScannerVC() {
    let scannerVC = BarCodeScannerViewController()
    scannerVC.onBarCodeReceived = { [weak self] scannedCode in
        guard let self = self else { return }
        self.BarCode = scannedCode
        // 这里可以直接刷新UI,比如更新表格数据
        self.tableView.reloadData()
    }
    self.present(scannerVC, animated: true, completion: nil)
}

解决方案2:代理模式(传统iOS数据回传方式)

如果更习惯用面向协议的方式,代理模式也是经典选择。

步骤1:定义代理协议

在SecondVC顶部声明协议:

protocol BarCodeScannerDelegate: AnyObject {
    func didFinishScanning(barCode: String)
}

class BarCodeScannerViewController: UIViewController {
    weak var delegate: BarCodeScannerDelegate?
    
    @objc func SendDataBack(_ button: UIBarButtonItem!) {
        delegate?.didFinishScanning(barCode: "Test")
        self.dismiss(animated: true, completion: nil)
    }
}

步骤2:让FirstVC遵循代理协议

class TableViewController: UITableViewController, BarCodeScannerDelegate {
    var BarCode: String = ""
    
    // 弹出扫描VC时设置代理
    func presentScanner() {
        let scannerVC = BarCodeScannerViewController()
        scannerVC.delegate = self
        self.present(scannerVC, animated: true, completion: nil)
    }
    
    // 实现代理方法接收数据
    func didFinishScanning(barCode: String) {
        self.BarCode = barCode
        self.tableView.reloadData()
    }
    
    // 在viewWillAppear中验证数据
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("BarCode - \(BarCode)") // 现在应该能输出"Test"了
    }
}

额外注意点

  • 不管用闭包还是代理,都要注意用[weak self]或weak var delegate避免循环引用,防止内存泄漏。
  • 尽量避免直接通过VC层级强转的方式传值,这种方式耦合性极高,一旦页面结构调整就会失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:05:57