20

Hi i am working on a universal application (iPhone/iPad). one feature is that i have to select a photo from album and show it on UIImageView.

Now problem is that it is working good on iPhone but when i try to open photo album it crashes. my code in action sheet delegate is this:

- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
        if ( ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))

        {   
            if (buttonIndex == 0)
            {
                [self lockAllImagesOnTheScreen];
                imagePicker.sourceType=UIImagePickerControllerSourceTypeCamera;
                [self presentModalViewController:imagePicker animated:YES];
            }
            if (buttonIndex == 1)
            {
                [self lockAllImagesOnTheScreen];

                imagePicker.sourceType= UIImagePickerControllerSourceTypePhotoLibrary;
                [self presentModalViewController:imagePicker animated:YES];
            }

        }
        else {

            if (buttonIndex == 0)
            {
                [self lockAllImagesOnTheScreen];
                imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                imagePicker.sourceType= UIImagePickerControllerSourceTypePhotoLibrary;
                [self presentModalViewController:imagePicker animated:YES];
            }
        }



    }

    else{
        if ( ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))

        {   
            if (buttonIndex == 0)
            {
                [self lockAllImagesOnTheScreen];
                imagePicker.sourceType=UIImagePickerControllerSourceTypeCamera;
                [self presentModalViewController:imagePicker animated:YES];
            }
            if (buttonIndex == 1)
            {
                [self lockAllImagesOnTheScreen];

                imagePicker.sourceType= UIImagePickerControllerSourceTypePhotoLibrary;
                [self presentModalViewController:imagePicker animated:YES];
            }

        }
        else {

            if (buttonIndex == 0)
            {
                [self lockAllImagesOnTheScreen];
                imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                imagePicker.sourceType= UIImagePickerControllerSourceTypePhotoLibrary;
                [self presentModalViewController:imagePicker animated:YES];
            }
        }


    }


}

can any body help me out? i have checked on stackOverflow and also googled it but in vain.

Felix
  • 35,354
  • 13
  • 96
  • 143
Mashhadi
  • 3,004
  • 3
  • 46
  • 80

4 Answers4

58

UIImagePickerController must be presented with UIPopoverController on iPad.

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
    [popover presentPopoverFromRect:self.selectedImageView.bounds inView:self.selectedImageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    self.popOver = popover;
} else {
    [self presentModalViewController:picker animated:YES];
}

EDIT: Add a strong property for the UIPopoverController:

@property (nonatomic, strong) UIPopoverController *popOver;

The popover should be dismissed in the delegate methods:

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

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker 
Felix
  • 35,354
  • 13
  • 96
  • 143
  • this answer is incomplete. what is self.popOver? there is no definition of it in the code presented – Sam B Jan 31 '13 at 00:16
  • 7
    It's not that incomplete, you just have to read between the lines... Obviously self.popOver is a property of type `UIPopoverController`, which presumably is used to handle closing the popup later. Just sayin' – mprivat Feb 24 '13 at 01:36
  • 3
    No, it is incomplete. If we are supposed to "read between the lines" then we at least need a direction to "read" into. This is a learning forum. Congrats for your iOs experience but no need to be rude. – edthethird Feb 26 '13 at 00:57
  • 2
    I would add also note about dismissing popover in `-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info` `-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker` `-(void)image:(UIImage *)image finishedSavingWithError:(NSError *)error contextInfo:(void *)contextInfo` – Pavel Dev Feb 28 '13 at 20:55
  • In this code... what is self.selectedImageView? I'm trying to do the same thing, but the camera is being limited to a very small window for some reason. (I suspect it's because of my misunderstanding of what selectedImageView is supposed to be...) – Dave Owens Apr 25 '14 at 14:03
6

Here i show you the SWIFT way:

import UIKit
class StoreItemViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate
{
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var productImage: UIImageView!
    var popOver:UIPopoverController?

    @IBAction func buttonSelected(sender:UIButton)
    {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum)
        {
            var imagePickerController = UIImagePickerController()
            imagePickerController.delegate = self
            imagePickerController.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum
            imagePickerController.allowsEditing = false

            if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad
            {
                self.popOver = UIPopoverController(contentViewController: imagePickerController)
                self.popOver?.presentPopoverFromRect(self.productImage.bounds, inView: self.productImage, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)      
            }
            else
            {
                self.presentViewController(imagePickerController, animated: true, completion: { imageP in

                })
            } 
        }
    }

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
         //do anything with the image
        let selectedImage = info[UIImagePickerControllerOriginalImage] as UIImage

        //closing the popup
        popOver?.dismissPopoverAnimated(true)

    }

    func imagePickerControllerDidCancel(picker: UIImagePickerController) 
    {
         println("cancel")

       //closing the popup
       popOver?.dismissPopoverAnimated(true)
    }
}
Peter Kreinz
  • 7,979
  • 1
  • 64
  • 49
4

The Apple docs say

"Present the user interface by calling the presentViewController:animated:completion: method of the currently active view controller, passing your configured image picker controller as the new view controller. On iPad, present the user interface using a popover. Doing so is valid only if the sourceType property of the image picker controller is set to UIImagePickerControllerSourceTypeCamera."

That says the exact opposite from how it behaves?!? You CANT present UIImagePickerControllerSourceTypeCamera from a popover and you CANT present UIImagePickerControllerSourceTypePhotoLibrary and UIImagePickerControllerSourceTypeSavedPhotosAlbum modally.

Strange...

cschuff
  • 5,502
  • 7
  • 36
  • 52
  • Can you provide a link? The Apple docs I can find say the opposite: you must use a popover for media browser... "On iPad, if you specify a source type of UIImagePickerController.SourceType.camera, you can present the image picker modally (full-screen) or by using a popover. However, Apple recommends that you present the camera interface only full-screen." https://developer.apple.com/documentation/uikit/uiimagepickercontroller – benc Mar 11 '19 at 17:17
3

POST iOS 8: Try adding popOver controller in

[[NSOperationQueue mainQueue] addOperationWithBlock:^{ }];

Reason : This is because in iOS 8, alert views and action sheets are actually presented view controllers (UIAlertController). So, if you're presenting a new view controller in response to an action from the UIAlertView, it's being presented while the UIAlertController is being dismissed. You need to do it on main queue without disturbing the navigation.

Zeeshan
  • 4,194
  • 28
  • 32