I don't know the solution yet, but I found a workaround without using AVCaptureMetadataOutput.
This workaround has been confirmed to work properly on iPad (7th Gen).
- Set AVCaptureVideoDataOutput to the output of AVCaptureSession instead of AVCaptureMetadataOutput.
captureSession.beginConfiguration()
// Add video input.
...
// Set AVCaptureVideoDataOutput to the output of AVCaptureSession.
let videodataOutput = AVCaptureVideoDataOutput()
if captureSession.canAddOutput(videodataOutput) {
captureSession.addOutput(videodataOutput)
// Set AVCaptureVideoDataOutputSampleBufferDelegate implemented object.
videodataOutput.setSampleBufferDelegate(delegate, queue: videoDataOutputQueue)
}
captureSession.commitConfiguration()
sessionQueue.async {
self.session.startRunning()
}
- Detect the barcode of the sampleBuffer received by the delegate using the Vision.framework
extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// convert sampleBuffer to CVImageBuffer.
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let handler = VNSequenceRequestHandler()
let barcodesDetectionRequest = VNDetectBarcodesRequest { (request, error) in
if let error = error {
// handle error.
NSLog("Error: %@", error.localizedDescription)
return
}
guard let results = request.results else { return }
for result in results {
if let barcode = result as? VNBarcodeObservation, validBarcodeTypes.contains(barcode.symbology),
let capturedCode = barcode.payloadStringValue {
NSLog("captured Code: %@", capturedCode)
}
}
}
// If necessary, specify the barcode type you want to detect.
barcodesDetectionRequest.symbologies = [.qr, .code128]
try? handler.perform([barcodesDetectionRequest], on: imageBuffer)
}
}