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

Swift 5使用通知传值:扫码后ViewController未触发通知回调问题

代码问题定位

  • 通知名称不匹配:发送通知用的名称是Notification.Name("scannedInfo"),监听用的是Notification.Name("ScanInfo"),名称不一致直接导致无法触发监听方法
  • 观察者注册时机完全错误:你在扫描完成后已经先发送了通知,又在dismiss的完成回调里新创建了一个ViewController1实例才去注册观察者,首先新创建的实例不是你之前发起跳转的原VC1实例,其次通知是即时发送的,注册前发送的通知不会被后续注册的观察者收到
  • 非全屏modal和这个问题没有关联,你现在的问题是逻辑错误,和弹出样式无关

修复方案

方案1:使用闭包回调(更推荐,逻辑更清晰,无通知全局污染)

  1. 首先在scanBarcode视图控制器中定义回调闭包:
class scanBarcode: UIViewController {
    // 定义扫描完成回调,参数为你要传回的条码值和value2
    var scanCompletion: ((_ barcode: String, _ value2: String) -> Void)?
    
    // 扫描完成的处理方法修改为:
    func processScan() {
        print("Process Scanned")
        let barcode = "123" // 替换为实际扫描得到的条码值
        let value2 = "Yes"
        // 先触发回调传值,再dismiss
        scanCompletion?(barcode, value2)
        dismiss(animated: true)
    }
}
  1. 弹出扫描页的时候绑定回调:
let scannerView = scanBarcode()
// 绑定回调,直接拿到返回值
scannerView.scanCompletion = { [weak self] barcode, value2 in
    guard let self = self else { return }
    self.barcode = barcode
    self.value2 = value2
    print(barcode)
    print(value2)
    // 拿到值后可以直接执行刷新UI等后续操作
}
let navigationController = UINavigationController(rootViewController: scannerView)
navigationController.modalPresentationStyle = .formSheet
self.present(navigationController, animated: true)

方案2:修正通知用法(如果一定要用通知的话)

  1. 统一通知名称,建议定义为全局常量避免拼写错误:
extension Notification.Name {
    static let scannedBarcodeInfo = Notification.Name("scannedBarcodeInfo")
}
  1. ViewController1需要在弹出扫描页之前就注册观察者,比如在viewDidLoad里注册:
class ViewController1: UIViewController {
    var barcode: String?
    var value2: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 页面加载完成就注册观察者
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(scanInfo(notification:)),
                                               name: .scannedBarcodeInfo,
                                               object: nil)
    }
    
    @objc func scanInfo(notification: Notification) {
        print("ScanInfo")
        barcode = notification.userInfo?["barcodeValue"] as? String
        value2 = notification.userInfo?["value2"] as? String
        print(barcode ?? "空值")
        print(value2 ?? "空值")
    }
    
    // 页面销毁时移除观察者,避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}
  1. 扫描完成的方法修改为:
func processScan() {
    print("Process Scanned")
    NotificationCenter.default.post(name: .scannedBarcodeInfo,
                                    object: nil,
                                    userInfo:["barcodeValue": "123","value2": "Yes"])
    dismiss(animated: true)
}

直接删除原代码中dismiss completion里创建ViewController1调用observeScanned的错误逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:24:02