How to use UIImagePickerController in iPad?

2019-01-09 01:42发布

问题:

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.

回答1:

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 


回答2:

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)
    }
}


回答3:

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...



回答4:

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.



回答5:

If the device is iPad and the source type is specified 'photoLibrary' or 'savedPhotosAlbum' UIImagePickerController must be presented popover according to the apple docs. In my case, I achieve my goal like this;

func choosePhotoFromLibrary() {
    let imagePicker = UIImagePickerController()
    imagePicker.sourceType = .photoLibrary
    imagePicker.delegate = self
    imagePicker.allowsEditing = true

    if UIDevice.current.userInterfaceIdiom == .pad {
        imagePicker.modalPresentationStyle = .popover
        present(imagePicker, animated: true, completion: nil)

        let imagePickerPopOverPresentationController = imagePicker.popoverPresentationController
        imagePickerPopOverPresentationController?.permittedArrowDirections = .up

        let photoPickingTableCell = tableView.cellForRow(at: IndexPath(row: 2, section: 0))

        imagePickerPopOverPresentationController?.sourceView = photoPickingTableCell
        imagePickerPopOverPresentationController?.sourceRect = profilePhotoImageView.frame
    }
    else {
        present(imagePicker, animated: true, completion: nil)
    }
}

I have a table view cell which includes an image view. Selecting that cell needs to open image picker controller, so calls choosePhotoFromLibrary method. In this method, if the device is pad, assign image picker's presentation style popover and present it. Then, configure the popover behaviour. In my case, my sourceView is table cell which includes image view, and my sourceRect is image view's frame.

You can also benefit from UIPopoverPresentationControllerDelegate methods if you assign a delegate.