Need to wait on completion of setFocusModeLockedWithLensPosition - Semaphore? Atomic? NSCondition?

130 Views Asked by At

I’ve not had much experience with semaphores, nor with blocks. I’ve seen various suggestions for how to turn an asynchronous call into a synchronous one. In this case I just want to wait to be sure the lens of the iPhone has changed focus before I snap another picture. I’ve added a completion block (with a little routine to prove that I’m seeing it). But how to block the rest of my code (running on the main thread) until I get the completion callback?

- (void) changeFocusSettings
{
    if ([SettingsController settings].useFocusSweep)
    {
        // increment the focus setting
        float tmp = [SettingsController settings].fsLensPosition;
        float fstmp =[[SettingsController settings] nextLensPosition: [SettingsController settings].fsLensPosition];  // get next lensposition
        [SettingsController settings].fsLensPosition = fstmp ;
        tmp = [SettingsController settings].fsLensPosition;
        if ([self.captureDevice lockForConfiguration: nil] == YES)
        {
            __weak typeof(self) weakSelf = self;
            [self.captureDevice setFocusModeLockedWithLensPosition:tmp
                                                 completionHandler:^(CMTime syncTime) {
                                                     NSLog(@"focus over..time = %f", CMTimeGetSeconds(syncTime));
                                                     [weakSelf focusCompletionHandler : syncTime];
                                                 }];
        }
    }
}

- (bool) focusCompletionHandler : (CMTime)syncTime
{
    NSLog(@"focus done, time = %f", CMTimeGetSeconds(syncTime));
    return true;
}

changeFocusSettings is called from another routine entirely. I image some kind of semaphore set just inside changeFocusSettings and then the focuscompletionHandler resets it. But the details are beyond me.
Thank you.

1

There are 1 best solutions below

0
On

I worked through it myself, it wasn't hard at all and it appears to be working. Here's the code in case it helps someone else. And if you happen to spot an error, please let me know.

dispatch_semaphore_t focusSemaphore;
...
- (bool) focusCompletionHandler : (CMTime)syncTime
{
    dispatch_semaphore_signal(focusSemaphore);
    return true;
}

- (void) changeFocusSettings
{
    focusSemaphore = dispatch_semaphore_create(0);  // create semaphone to wait for focuschange to complete
    if ([SettingsController settings].useFocusSweep)
    {
        // increment the fsLensposition
        float tmp = [SettingsController settings].fsLensPosition;
        float fstmp =[[SettingsController settings] nextLensPosition: [SettingsController settings].fsLensPosition];  // get next lensposition
        [SettingsController settings].fsLensPosition = fstmp ;
        tmp = [SettingsController settings].fsLensPosition;
        NSLog(@"focus setting = %f and = %f", tmp, fstmp);
        if ([self.captureDevice lockForConfiguration: nil] == YES)
        {
            __weak typeof(self) weakSelf = self;
            [self.captureDevice setFocusModeLockedWithLensPosition:tmp
                                                 completionHandler:^(CMTime syncTime) {
                                                                [weakSelf focusCompletionHandler : syncTime];

                                                     }];
            dispatch_semaphore_wait(focusSemaphore, DISPATCH_TIME_FOREVER);
        }
    }
}