0

I have been trying this for the past 2 days and I am not able to figure out the answer. I have searched all over and I haven't found the answer.

The question is I have a button which brings up the camera in my app(to take photos only). The camera opens up, but when i take a picture and click on "USE"(which is displayed at the bottom right) its crashing. Also, when the camera opens up, before taking a picture when I click "Cancel" it again crashes.

I tried using breakpoints and found out that, When I click on the "USE" button, it crashes in this line

[picker dismissViewControllerAnimated:YES completion:Nil]

I'm testing it in my iPad (iOS6).

Here is the Button Code here :

-(IBAction)getAlbum:(id)sender {

    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        NSArray *media = [UIImagePickerController
                          availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeCamera];

        if ([media containsObject:(NSString*)kUTTypeImage] == YES) {
            UIImagePickerController *picker = [[UIImagePickerController alloc] init];
            picker.sourceType = UIImagePickerControllerSourceTypeCamera;
            //picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
            [picker setMediaTypes:[NSArray arrayWithObject:(NSString *)kUTTypeImage]];

            picker.delegate = self;
            //[self presentModalViewController:picker animated:YES]; //Since [Modal](http://stackoverflow.com/questions/12445190/dismissmodalviewcontrolleranimated-deprecated) has been removed
            [self presentViewController:picker animated:YES completion:Nil];
            //[picker release];

        }
        else {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unsupported!"
                                                            message:@"Camera does not support photo capturing."
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
            [alert release];
        }

    }
    else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unavailable!"
                                                        message:@"This device does not have a camera."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }


}

imagePickerController Method here:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    NSLog(@"Media Info: %@", info);
    NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];

    if([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
        UIImage *photoTaken = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

        //Save Photo to library only if it wasnt already saved i.e. its just been taken
        if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
            UIImageWriteToSavedPhotosAlbum(photoTaken, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
        }


        selectedLogoImg.image=photoTaken; //selectedLogoImg is the imageView
        [self.clipartItemView addSubview:selectedLogoImg]; // To detect touch and move it I place it as a subview of self.clipartItemView
    }

    //[picker dismissModalViewControllerAnimated:YES];
    [picker dismissViewControllerAnimated:YES completion:Nil]
    //[picker release];
    //[picker dismissViewControllerAnimated:YES completion:^{
      //  NSLog(@"Dismiss completed");
    //}];
}

didFinishSavingWithError Code Here:

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    UIAlertView *alert;
    //NSLog(@"Image:%@", image);
    if (error) {
        alert = [[UIAlertView alloc] initWithTitle:@"Error!"
                                           message:[error localizedDescription]
                                          delegate:nil
                                 cancelButtonTitle:@"OK"
                                 otherButtonTitles:nil];
        [alert show];
        [alert release];
    }

}

imagePickerControllerDidCancel Code Here:

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    //[picker dismissModalViewControllerAnimated:YES];
    /*[picker dismissViewControllerAnimated:YES completion:^{
        [self.view sendSubviewToBack:cardGalleryView];
    }];*/
    [picker dismissViewControllerAnimated:YES completion:Nil];

}
Vikr
  • 121
  • 1
  • 7

2 Answers2

1

You should send the dismissViewControllerAnimated:completion: message to the view controller, not the picker. Try:

[self dismissViewControllerAnimated:YES completion:nil];

The above method is only for iOS 6. You need to use [self dismissModalViewControllerAnimated:YES] for iOS 5 and below.

Take a look at the description of the method in the documentation:

Dismisses the view controller that was presented by the receiver.

The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, however, it automatically forwards the message to the presenting view controller

Valent Richie
  • 5,226
  • 1
  • 20
  • 21
  • Should i do that in imagePickerControllerDidCancel or imagePickerController Method ? – Vikr May 23 '13 at 10:44
  • @Vikr in every line where you are trying to dismiss the picker, basically every occurrence of `[picker dismissViewControllerAnimated:YES completion:Nil];` in your existing code. – Valent Richie May 23 '13 at 10:46
  • dismissModalViewControllerAnimated is deprecated in ios6 and they suggest to use dismissViewControllerAnimated ? – Vikr May 23 '13 at 10:48
  • @Vikr no, they suggest to use dismissViewControllerAnimated:completion:, with the difference of newly added completion method. – Valent Richie May 23 '13 at 10:50
  • You want me to use [self dismissModalViewControllerAnimated:YES completion:nil]; - like you suggested or [self dismissViewControllerAnimated:YES completion:Nil]; – Vikr May 23 '13 at 10:53
  • @Vikr maybe you can try both first and see what you find. :) – Valent Richie May 23 '13 at 11:01
  • its crashing when i try with my original code, I cant use what you have suggested - [self dismissModalViewControllerAnimated:YES completion:nil]; since this is not valid in iOS6. When i try [self dismissViewControllerAnimated:YES completion:Nil]; im getting this error - *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' *** First throw call stack: – Vikr May 23 '13 at 11:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/30482/discussion-between-verbumdei-and-vikr) – Valent Richie May 23 '13 at 11:12
0

This problem is due to your UIImagePickerController *picker object . ViewController isn't able to identify your picker object reference out of the getAlbum method scope.

1.> you can create UIImagePickerController object in your .h file

 @interface yourViewController : UIViewController <UIImagePickerControllerDelegate,UINavigationControllerDelegate,UINavigationControllerDelegate,UIPopoverControllerDelegate>
{

   UIImagePickerController *picker;
   UIPopoverController *popover;
} 

and in .m file you just use it inside getAlbum IBAction method

-(IBAction)getAlbum:(id)sender {

if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    NSArray *media = [UIImagePickerController
                      availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeCamera];

    if ([media containsObject:(NSString*)kUTTypeImage] == YES) {

         UIButton *btn=(UIButton *)sender;
         if ([popover isPopoverVisible])
         {
              [popover dismissPopoverAnimated:YES];
              popover=nil;
         }
         picker = [[UIImagePickerController alloc]init];
         picker.sourceType = UIImagePickerControllerSourceTypeCamera;
         [picker setMediaTypes:[NSArray arrayWithObject:(NSString *)kUTTypeImage]];
         picker.delegate = self;

        popover = [[UIPopoverController alloc] initWithContentViewController:picker];
        [popover presentPopoverFromRect:CGRectMake(btn.frame.size.width,btn.frame.size.height/2,1,1) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];

    }
    else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unsupported!"
                                                        message:@"Camera does not support photo capturing."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }

 }
 else {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unavailable!"
                                                    message:@"This device does not have a camera."
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];
 }
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)myimage editingInfo:(NSDictionary *)editingInfo
{
    myimage = [myimage fixOrientation];

    [picker dismissModalViewControllerAnimated:YES];
    [popover dismissPopoverAnimated:YES];
}

I hope it helps you to better understand.

chandan
  • 2,453
  • 23
  • 31
  • Its crashing as usual. I'm using iOS6 in my iPad and I cant use dismissModalViewControllerAnimated. I can only use [self dismissViewControllerAnimated:YES completion:Nil]; which is also returning error – Vikr May 23 '13 at 11:10
  • Hi Vikr, Please have a look on my updated code and use didFinishPickingImage: instead of didFinishPickingMediaWithInfo: . If you are using ipad then picker would work with UIPopoverController so if any UIPopoverController obeject is avaliable then use [popover dismissPopoverAnimated:YES]; for it. – chandan May 23 '13 at 11:19
  • Hi Vikr, 'On iPad, UIImagePickerController must be presented via UIPopoverController'. This is rule by apple otherwise your app will reject in appstore so for ipad implement UIImagePickerController via UIPopoverController – chandan May 23 '13 at 11:28
  • Yes, I'm testing my app in a iPad.. Actually ViewWillAppear is playing the spoil sport. If i comment it, the above code is working. But then, other work called in viewwillappear seems to be not working. – Vikr May 23 '13 at 13:19
  • you should apply UIPopoverController inside getAlbum for picking image from camera. With out an UIPopoverController in an ipad app , Apple reject your application under review period so try to apply it with UIPopoverController. I m updating my code with your getAlbum method . Use it and apply – chandan May 23 '13 at 13:33
  • My original code is working. I just had to set a BOOL for viewWillAppear and use it in my existing code. – Vikr May 29 '13 at 06:35