如何让VisionKit的DataScannerViewController仅识别VIN码与Code39条码?
实现VisionKit仅识别VIN码和Code39条码
要让DataScannerViewController只识别VIN码和Code39条码,需要从扫描类型配置和结果过滤两方面入手,同时优化用户体验避免无效内容干扰:
1. 配置扫描类型
首先限制扫描器仅识别Code39条码和英文文本(VIN码由大写字母和数字组成):
@available(iOS 16.0, *) extension DataScannerViewController { static func makeDatascanner(delegate: DataScannerViewControllerDelegate) -> DataScannerViewController { let scanner = DataScannerViewController( recognizedDataTypes: [ .barcode(symbologies: [.code39]), // 仅启用Code39条码识别 .text(languages: ["en"]) // 仅识别英文文本(适配VIN码字符集) ], isGuidanceEnabled: true, isHighlightingEnabled: false // 关闭默认高亮,后续自定义有效VIN的高亮 ) scanner.delegate = delegate return scanner } }
2. 过滤无效扫描结果
在代理方法中,只处理符合VIN格式的内容(17位,不含I/O/Q),并忽略其他所有识别结果:
@available(iOS 16.0, *) extension ScannerViewController: DataScannerViewControllerDelegate { // 处理新增识别项 func dataScanner( _ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem] ) { processValidVINItems(from: addedItems) } // 处理更新的识别项 func dataScanner( _ dataScanner: DataScannerViewController, didUpdate updatedItems: [RecognizedItem], allItems: [RecognizedItem] ) { processValidVINItems(from: updatedItems) } // 处理移除的识别项(清理对应高亮视图) func dataScanner( _ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem] ) { // 可在此移除对应无效项的自定义高亮视图 } // 处理点击事件 func dataScanner( _ dataScanner: DataScannerViewController, didTapOn item: RecognizedItem ) { switch item { case let .text(text) where isValidVIN(text.transcript): delegate?.scannerViewController(self, didScanString: text.transcript) case let .barcode(barcode) where isValidVIN(barcode.payloadStringValue ?? ""): delegate?.scannerViewController(self, didScanString: barcode.payloadStringValue ?? "") default: break // 直接忽略无效点击 } } // 过滤并处理有效VIN项(添加自定义高亮) private func processValidVINItems(from items: [RecognizedItem]) { let validVINs = items.filter { item in switch item { case let .text(text): return isValidVIN(text.transcript) case let .barcode(barcode): return isValidVIN(barcode.payloadStringValue ?? "") default: return false } } // 为有效VIN绘制自定义高亮框 validVINs.forEach { item in let frame: CGRect switch item { case let .text(text): frame = text.boundingBox case let .barcode(barcode): frame = barcode.boundingBox default: return } let overlay = UIView() overlay.layer.borderColor = UIColor.systemGreen.cgColor overlay.layer.borderWidth = 2 overlay.frame = frame dataScanner.view.addSubview(overlay) } } // VIN格式验证(符合ISO标准:17位,排除I/O/Q) private func isValidVIN(_ vin: String) -> Bool { let vinRegex = "^[A-HJ-NPR-Z0-9]{17}$" let vinPredicate = NSPredicate(format: "SELF MATCHES %@", vinRegex) return vinPredicate.evaluate(with: vin) } }
关键优化点
- 关闭默认高亮:避免无关文本被高亮,仅对有效VIN绘制自定义高亮,减少用户干扰。
- 提前过滤结果:在
didAdd/didUpdate阶段就过滤无效内容,减少后续处理逻辑。 - 严格格式校验:用正则表达式确保只有符合标准的17位VIN码被识别。
内容的提问来源于stack exchange,提问作者Christian W
相关产品推荐
相关产品推荐

