已用Swift+AVFoundation实现条码阅读器,请求新增Code39Mod10与Codabar支持
Hey there! Let’s walk through how to add support for these two barcode types to your existing Swift/AVFoundation reader—they’re totally manageable with a mix of native AVFoundation features and a little custom logic.
1. Adding Codabar Support
Good news: AVFoundation actually has built-in support for Codabar that you might have overlooked. Just add the AVMetadataObjectTypeCodabarCode constant to your supportedCodeTypes array, right alongside your existing types:
let supportedCodeTypes = [ AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeAztecCode, AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, // Add Codabar here AVMetadataObjectTypeCodabarCode // ... any other remaining types you had ]
Once added, AVFoundation will detect Codabar barcodes automatically, just like all the types you’re already handling. No extra work needed here!
2. Adding Code39Mod10 Support
Code39Mod10 is a variant of standard Code39 that includes a Mod10 check digit for validation. AVFoundation doesn’t have a dedicated metadata type for it, but it will still scan Code39Mod10 barcodes as regular Code39. To fully support it, you’ll need to add custom logic to validate the check digit after scanning.
Step 1: Keep AVMetadataObjectTypeCode39Code in your supported list
Make sure this constant stays in your supportedCodeTypes—it’s how AVFoundation will pick up the Code39Mod10 barcode in the first place.
Step 2: Build a helper function to validate the Mod10 check digit
Create a function to verify that the scanned Code39 string has a valid Mod10 check digit:
func isCode39Mod10Valid(_ code: String) -> Bool { // Code39Mod10 uses the last character as the check digit guard code.count >= 2 else { return false } let payload = String(code.dropLast()) guard let checkDigit = code.last else { return false } // Map Code39 characters to their numerical values let characterValues: [Character: Int] = [ "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16, "H": 17, "I": 18, "J": 19, "K": 20, "L": 21, "M": 22, "N": 23, "O": 24, "P": 25, "Q": 26, "R": 27, "S": 28, "T": 29, "U": 30, "V": 31, "W": 32, "X": 33, "Y": 34, "Z": 35, "-": 36, ".": 37, "$": 38, "/": 39, "+": 40, "%": 41 ] // Calculate sum of all payload character values var sum = 0 for char in payload { guard let value = characterValues[char] else { return false } sum += value } // Compute the expected check digit and compare to the scanned one let expectedCheckDigitValue = sum % 10 guard let actualCheckDigitValue = characterValues[checkDigit], actualCheckDigitValue == expectedCheckDigitValue else { return false } return true }
Step 3: Use the validator in your detection callback
When AVFoundation returns a scanned Code39 barcode, run it through the validator to distinguish valid Code39Mod10 barcodes from standard Code39:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject, let scannedValue = metadataObject.stringValue else { return } switch metadataObject.type { case AVMetadataObjectTypeCode39Code: if isCode39Mod10Valid(scannedValue) { // Handle valid Code39Mod10 barcode print("Valid Code39Mod10 detected: \(scannedValue)") } else { // Handle standard Code39 or invalid Code39Mod10 print("Standard Code39 or invalid Code39Mod10: \(scannedValue)") } // Handle your other barcode types here... default: print("Scanned \(metadataObject.type.rawValue): \(scannedValue)") } }
Quick Recap
- Codabar is a no-brainer—just add the native AVFoundation constant to your supported list.
- Code39Mod10 needs a little extra work: AVFoundation scans it as standard Code39, so you’ll use your custom validator to confirm the check digit is valid.
内容的提问来源于stack exchange,提问作者mahega

