RobertJoseph RobertJoseph - 18 days ago 5
iOS Question

Simulate a "picture taken" screen flash

I have an AV Foundation app that simulates taking a picture (like the camera app). Normally the following works for me, but isn't in this instance.

This code executes within an action in my view controller. It contains a single full-screen UIView (videoPreviewLayer) which has a AVCaptureVideoPreviewLayer attached. The animation executes but nothing is displayed. Note also that I am using ARC, iOS 6, iPhone 4S, iPad3.

// Flash the screen white and fade it out
UIView *flashView = [[UIView alloc] initWithFrame:[[self videoPreviewView] frame]];
[flashView setBackgroundColor:[UIColor whiteColor]];
[[[self view] window] addSubview:flashView];

[UIView animateWithDuration:1.f
animations:^{
[flashView setAlpha:0.f];
}
completion:^(BOOL finished){
[flashView removeFromSuperview];
}
];


Here is how I attach the AVCaptureVideoPreviewLayer:

// Setup our preview layer so that we can display video from the camera
captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];

CALayer *viewLayer = videoPreviewView.layer;
viewLayer.masksToBounds = YES;

captureVideoPreviewLayer.frame = videoPreviewView.bounds;

[viewLayer insertSublayer:captureVideoPreviewLayer below:[[viewLayer sublayers] objectAtIndex:0]];


NOTE After further investigation, the flash is occurring although intermittently. Generally it seems to become visible about 5-10 seconds after it should start. I've also seen it happen run twice in quick succession even though I call the code once.

Answer

My problem was that the "flash" code was being called from an AV Foundation callback. The callback was not running on the main thread thus any UI code wouldn't execute correctly. That solution was to do something like this:

dispatch_async(dispatch_get_main_queue(), ^{ /* execute flash code */ });
Comments