Looking at some Apple code sample, I found this:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// wait() is used to drop new notifications if old ones are still processing, to avoid queueing up a bunch of stale data.
if metadataObjectsOverlayLayersDrawingSemaphore.wait(timeout: .now()) == .success {
DispatchQueue.main.async {
// Some processing...
self.metadataObjectsOverlayLayersDrawingSemaphore.signal()
}
}
}
Context of the code: This is the delegate method when using video capture to detect a QR code (or any other code). Because it is triggered many times per second (if the camera stays on the same QR code), some kind of timeout is needed.
But how does DispatchSemaphore.wait(timeout: .now())
work? And why check if it is .success
?
The purpose is what the comment says:
wait() is used to drop new notifications if old ones are still processing, to avoid queueing up a bunch of stale data.
and it works as follows:
metadataOutput
is called the first time, wait(timeout: .now())
succeeds and decrements the value of the semaphore to zero.
The processing of the data begins.metadataOutput
is called again before the processing has
completed, the semaphore still has a value of zero.
Then wait(timeout:)
would wait for the semaphore to become
positive again, but since the timeout value is now()
, it fails
immediately and returns .timedOut
.
The effect is that the incoming data is ignored, the metadataOutput
callback method returns immediately.So in short:
wait(timeout: .now())
returns .success
if a
previously submitted block has signaled completion, in that case
a new block is submitted for processing the incoming data.wait(timeout: .now())
returns .timedOut
if a previously
submitted block is still running, in that case the incoming data
is ignored.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With