Question

I would like to present a UIImagePickerController immediately when a user tabs on the camera tab in my app to take a photo (similar to many photo taking apps like Instagram, etc). Currently, I have a VC called CameraViewController that displays the picture taken from the UIImagePickerController, and in the viewWillAppear function of CameraViewController I present the ImagePickerController modally when I detect that no picture have been taken.

While this worked most of the time, I noticed that at times I would get an exception saying:

"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller ."

Per the suggestion of some SO questions here, I also tried presenting the controller in viewDidAppear. However, with viewDidAppear, the modal ImagePicker is never dismissed, and I keep getting the error "Unbalanced calls to begin/end appearance transitions for ."

My questions are:

  1. I am currently presenting the ImagePickerController modally for the user to take a picture, and then dismissing it once the picture is taken. Is this generally the way things are done with ImagePickerControllers that are the most reliable/problem-free.
  2. Where else should I consider putting the ImagePickerController in the view life cycle to get this desired effect?

Here is my code:

in viewWillAppear

BOOL modalPresent = (BOOL)(self.presentedViewController);
if (!appDelegate.imageStorageDictionary[@"picture1"]){
    if (modalPresent == NO){
        [self presentViewController:self.imagePickerController animated:NO completion:nil];
    }
}

in imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

//Other lines omitted 
if (![[self imagePickerController] isBeingDismissed]) 
    [self dismissViewControllerAnimated:NO completion:nil];
Was it helpful?

Solution

I am not getting much about your question regarding -viewWillAppear , but one thing you must know that -viewWillAppear would be called more than one time(s). reason being , the first call will be when your viewController is loaded and viewDidLoad and appear would be called as usual, secondly when you have presented amodalViewController (imagePickerController) and when it is dismissed again viewWillAppear will be called because the viewController's view is about to appear..

Secondly regarding you want present camera's functionality when user taps on camera button , do this:

  if([UIImagePickerControllerisSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
     if(myPicker)
     {
        [myPicker release];
         myPicker = nil;
      }
 myPicker   = [[UIImagePickerController alloc] init];

     [self presentViewController:myPicker animated:YES completion:NULL];
}
else
{
    UIAlertView *altnot=[[UIAlertView alloc]initWithTitle:@"Camera Not Available" message:@"Camera Not Available" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    altnot.tag=103;
    [altnot show];
    [altnot release];
}

for picking already captured images..

-(void)ChooseAlreadyCapturedPhoto {

if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
    if(myPicker)
    {
       [myPicker release];
       myPicker = nil;
    }
    myPicker          = [[UIImagePickerController alloc] init];
    myPicker.delegate = self;
    myPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

    myPicker.allowsEditing = NO;

}
[self presentViewController:myPicker animated:YES completion:NULL];

}

Note: I have released previously allocated object of picker every time when I am using it, but it is not necessary. You can use the only single instance of my picker, don't mark it wrong. And using imagePicker-controller inside viewController is absolutely fine, it won't harm.. If you present and dismiss modalViewController a no. times, then viewWill appear also would be called , each time you dismiss it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top