27

When [camera takePicture] is called before the camera is ready, it spits out this message:

UIImagePickerController: ignoring request to take picture; camera is not yet ready.

How can I know when it is ready to take a photo?

[camera isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] always returns true, even when it's apparently not ready.

James Skidmore
  • 49,340
  • 32
  • 108
  • 136
  • Similar question at http://stackoverflow.com/questions/6817920/recored-video-using-uiimagepickercontroller - the selected answer is incorrect, but there is another answer which talks about adding a delay. This is probably a good starting point. – Tass May 21 '12 at 00:50
  • Also, see http://stackoverflow.com/questions/4377303/uiimagepickercontroller-camera-not-ready - seems there is a return code when the camera isn't ready. Check the result, wait, and try again. – Tass May 21 '12 at 00:51
  • I sure hope a delay isn't the only way to go, although it seems like it. Surely there's a better solution... – James Skidmore May 21 '12 at 05:45
  • Can you target iOS 4+ devices? There is a solution but it needs AVFoundation instead of UIImagePickerController. – djromero May 24 '12 at 15:45
  • Yes, I'm looking at a minimum of iOS 4.2.1. – James Skidmore May 24 '12 at 15:47

7 Answers7

46

As @djromero said there is a solution by using AVFoundation (but not instead of UIImagePickerController. You just use AVFoundation to get a notification back).

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(cameraIsReady:)
                                             name:AVCaptureSessionDidStartRunningNotification object:nil];

And then, once the camera is ready you got your notification:

- (void)cameraIsReady:(NSNotification *)notification
{   
    NSLog(@"Camera is ready...");
    // Whatever
}

I have just tested it by calling takePicture after UIImagePickerController presentation (where I got the 'camera is not ready' message) and right inside my notification callback, where it worked like a charm.

Side-note:

[camera isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] always returns Yes because it only checks that there is a camera device available. As a matter of fact, Apple recommends that you always must check that this returns Yes and that you have a non nil delegate (to provide a way to dismiss the picker through the standard interface) before you try to initialize and present the controller.

djromero
  • 19,551
  • 4
  • 71
  • 68
Alladinian
  • 34,483
  • 6
  • 89
  • 91
  • Awesome answer. This is incredibly useful. Haven't had a chance to plug it in yet, but I'm assuming from the upvotes that it works. Thank you Alladinian!!! – James Skidmore Jun 05 '12 at 00:53
  • @JamesSkidmore You're welcome! Indeed, this one is so useful that Apple should have documented it better or at least provide a higher-level api (via a delegate method for example) inside `UIImagePickerController`. – Alladinian Jun 05 '12 at 09:11
  • This is not working in iOS 4.2.1. No errors, it's just that the callback method is never executed. Any ideas? – James Skidmore Jun 09 '12 at 19:19
  • @JamesSkidmore Hmm that's strange. It's definitely working in iOS5 and documentation states that the notification is available for iOS4+. I 'll have a look and let you know if I find something. (You have imported `AVFoundation`, right?) – Alladinian Jun 09 '12 at 19:25
  • Thanks Alladinian. Yes, `AVFoundation` is imported, but it's still not working. – James Skidmore Jun 09 '12 at 19:42
  • @JamesSkidmore Is the device you're running capable of recording video? – Alladinian Jun 09 '12 at 19:49
  • Oh... good point! This particular device is an iPhone 3G which cannot record video. So I'm guessing the notification is not sent on non-video capable devices? Is there another notification that is sent instead? – James Skidmore Jun 09 '12 at 20:19
  • I just tested it also on a 3G and you're right, no notification is posted. I don't think that there is some other notification posted and it looks like a bug to me. I will ask Apple in the dev forums and I will try some _hack_ that may work. I'll let you know. – Alladinian Jun 09 '12 at 20:30
  • OK thanks for the help Alladinian. I'll try thinking of something as well, and let's see what we come up with. – James Skidmore Jun 10 '12 at 02:38
  • In my case I am using an overlay view that has a shutter button. How can I use this techniques in this scenario? @djromero – Camus Apr 14 '14 at 11:08
  • This is good for taking a single image, but won't tell you how long to wait until you capture another. The notif is only posted once, unfortunately. Are there any alternatives for that which do not involve using AVFoundation directly? – oarfish Jun 11 '15 at 09:30
  • iOS 9.1 - This did not work for me. But I got it to work by adding a .1 second delay in this method using a dispatch_after(). – John Fowler Feb 18 '16 at 21:08
1

To be honest I haven't tried it and the documentation is somewhat ambiguous, but what about [UIImagePickerController isCameraDeviceAvailable:...]?

EDIT: As I just learned, this is not the solution for your problem. Sorry, I thought it might be worth a try...

Stefan
  • 1,347
  • 2
  • 16
  • 38
0

What @Alladinian said was most helpful, this answer is supplemental to that. I recommend using his AVCaptureSessionDidStartRunningNotification technique as that tells you when the camera is ready initially (but this is called only once.) I am also concerned with if the device is ready for subsequent pictures as well. I haven't found the best solution, because I don't see any call backs for the device that don't refer to the camera's session. But this callback function seems to be good enough:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

Note the camera most likely will be ready before that callback is called, and you can cram in one or two photos, but it seems that the camera will definitely be ready by the time the callback is called. This should keep you from getting the following error between multiple camera shots.

UIImagePickerController: ignoring request to take picture; image is already being captured or camera not yet ready.
trevorgrayson
  • 1,806
  • 1
  • 21
  • 29
0

As per the documentation for UIImagePickerController. The takePicture() method is ready again when

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

is called. If your interested in blocking pictures during this time period just disable the button interface (button.userInterfaceEnabled = false) until the call returns with media. I solved this very problem using the imagePickerController.

Scott Jenkins
  • 321
  • 2
  • 7
0

Here is a Swift Version :

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.cameraIsReady), name: AVCaptureSessionDidStartRunningNotification, object: nil)


func cameraIsReady(notification :NSNotification ) {
     print("Camera is ready...")
}
Steve
  • 1,022
  • 2
  • 9
  • 30
-1

If you are using UIImagePickerController, following is the code for video, similar code implies for image as well.

UIImagePickerController *picker;
BOOL cameraIsOn;

Then check for camera device available

if ([UIImagePickerController isCameraDeviceAvailable:[picker cameraDevice]]) {
            if (cameraIsOn) {
                NSLog(@"stop camera");
                [picker stopVideoCapture];
                cameraIsOn = FALSE;
            }
            else {
                NSLog(@"start camera");
                [picker startVideoCapture];
                self.videoTimer =  [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(changeValue) userInfo:nil repeats:YES];
                cameraIsOn = TRUE;
            }
        }
Bishal Ghimire
  • 2,580
  • 22
  • 37
-1

This makes sure to start capturing video as soon as camera is ready

imgpicker = [[UIImagePickerController alloc] init];  
[self presentViewController:imgpicker animated:YES completion:^(void){       
while(![imgpicker startVideoCapture]);
}];
Dennis Meng
  • 5,109
  • 14
  • 33
  • 36