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
相关产品推荐
相关产品推荐

