In my app I have a QR code scanner which uses AVFoundation
to show the scan preview and read the code data. For some reason, it takes a very long time to add the AVCaptureMetadataOutput
for QR reading to the AVCaptureSession
the second time the view controller (which manages the capture session) appears. The first time it appears, on the other hand, the view controller is able to set up the capture session, the input and the output pretty much within a second. But the next time, however, it gets stuck on AVCaptureSession
's addOutput:
for about 15–20 seconds before it finally returns.
The view controller which manages the QR scanning session looks something like this:
init() {
session = AVCaptureSession()
}
func viewDidLoad() {
dispatch_async(dispatch_get_global_queue(0, 0), {
// Handle video input...
let videoDevice = /* get AVCaptureDevice */
self.videoDeviceInput = AVCaptureDeviceInput.deviceInputWithDevice(videoDevice, error: nil)
self.session.addInput(videoDeviceInput)
// Handle QR code output...
self.metadataOutput = AVCaptureMetadataOutput()
self.metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
self.session.addOutput(metadataOutput) /* takes 15 to 20 seconds after first time */
self.metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
})
}
func viewWillAppear(animated: Bool) {
dispatch_async(dispatch_get_global_queue(0, 0), {
self.session.startRunning()
})
}
func viewWillDisappear(animated: Bool) {
dispatch_async(dispatch_get_global_queue(0, 0), {
self.session.stopRunning()
})
}
So what tends to happen is, when the view controller appears the second time, the video preview appears instantly, but it takes 15 seconds or more before the QR code the camera's pointed at scans (because of addOutput:
taking such a long time). It happens on a separate thread, so at the least user interface remains responsive, but is there any way to fix the long during of addOutput:
? Am I not cleaning up properly after the first time it scans? Is there something else?
I'm not certain why, but it looks like the reason it was taking so long was because I was using dispatch_get_global_queue(0, 0)
. Instead, I created my own queue:
let queue = dispatch_queue_create("com.myApp.avfoundation", nil)
And used that instead of getting a global queue for all the operations with AVFoundation:
dispatch_async(queue, {
…
}