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