iOS9上iPad的UIImagePickerController

32
自从iOS 9和Xcode 7以后,我无法在iPad(设备和模拟器)上实现UIImagePickerController。下面的代码适用于iPad,但仅限于iOS 9之前的版本。当使用iOS 9+时,所呈现的图像(在UIImagePickerController被解除显示后)是所选图像的不正确版本。如果没有重新调整大小或裁剪,最终图像只是原始图像的右上角?另外一个问题是 - 如果imagePicker.allowsEditing = false,则无法从PhotoLibrary中选择图像?
@IBAction func photoButton(sender: AnyObject) {    

    imagePicker.allowsEditing = true
    imagePicker.sourceType = .PhotoLibrary

    self.presentViewController(imagePicker, animated: false, completion: nil)

}


func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {

    self.imageView.image = pickedImage

    dismissViewControllerAnimated(true, completion: { () -> Void in
            })    

}

这里是在UIImagePickerController中呈现所选图像的示例。(请注意,所选图像的呈现非常小,而不是全屏幕/宽度)

enter image description here

在UIImagePickerController中选择使用按钮后,最终图像仅为原始图像的右上角。我做错了什么或是UIImagePickerController在iOS 9上有问题吗?

enter image description here


你应该将图片适应到你的ImageView中。 - Teja Nandamuri
1
尝试过了,没有任何不同。问题在于UIImagePickerController内部。我刚刚用Objective C重写了上述代码,一切正常,所以使用SWIFT 2是错误的吗? - pete
imageView是一个IBOutlet还是一个属性? - Teja Nandamuri
7个回答

11

这是苹果的一个漏洞: http://openradar.appspot.com/radar?id=5032957332946944

目前可行的解决方法比较差劲:

 if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
         imagePicker.allowsEditing = false
     } else {
         imagePicker.allowsEditing = true
     }

Swift 3.0:

if UIDevice.current.userInterfaceIdiom == .pad {
}

这应该是被接受的答案。其他冗长的回答都是误导性的,读起来浪费时间,因为它们通过将allowsEditing设置为false或在iPhone而不是iPad上运行来“修复”问题。 - chetstone
1
在“didFinishPickingMediaWithInfo”中进行相同的检查,并分别设置UIImagePickerControllerOriginalImage / UIImagePickerControllerEditedImage,以完成此解决方法的另一半...至少在他们修复这个问题之前,你仍然可以拥有iPhone设备所喜欢的功能... - edhnb

4
请参考以下代码。
@IBAction func photoButton(sender: AnyObject)
{
   if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera))
   {
     picker!.sourceType = UIImagePickerControllerSourceType.Camera
     self .presentViewController(picker!, animated: true, completion: nil)
   }
   else
   {
     let alertWarning = UIAlertView(title:"Warning", message: "You don't have camera", delegate:nil, cancelButtonTitle:"OK", otherButtonTitles:"")
     alertWarning.show()
   }
}
func openGallary()
{
   picker!.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
   self.presentViewController(picker!, animated: true, completion: nil)
}

//PickerView Delegate Methods
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
{
   picker .dismissViewControllerAnimated(true, completion: nil)
   imageView.image=info[UIImagePickerControllerOriginalImage] as? UIImage
}
func imagePickerControllerDidCancel(picker: UIImagePickerController)
{
   println("picker cancel.")
}

1
是的,问题出在信息字典中的“UIImagePickerControllerEditedImage”键上。使用“UIImagePickerControllerOriginalImage”将起作用,即使这并不理想。 - fedoroffn

3

您需要确保您的imageview使用正确的frame,且contentmode应为aspectfit。选择器返回的图像类型应为[UIImagePickerControllerOriginalImage]

[imageView setFrame:imageViewRect];
[imageView setContentMode:UIViewContentModeScaleAspectFit];

Swift:

 imageView.setFrame(imageViewRect)
 imageView.setContentMode(UIViewContentModeScaleAspectFit)

提到allowsEditing属性,它与照片选择无关。

这是一个布尔值,表示用户是否允许编辑所选的静态图像或电影。

如果您想从相机库中选择照片,则需要修改源类型为

    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

更新:

假设您已经选择了一张图片并将其显示在图像视图上。我假设您在视图上有一个图像视图,并且图像视图的框架与视图框架相等。如果IB是自由形式的,则假定IB中图像视图框架的大小为600x600。

如果您只是这样做:

     _startImageView.image=_img;

结果将是:

enter image description here

现在,让我们对要显示在图像视图中的图像进行一些更改:
  CGRect scaledRect = AVMakeRectWithAspectRatioInsideRect(_img.size, CGRectMake(0, 0, self.startImageView.frame.size.width, self.startImageView.frame.size.height));
UIGraphicsBeginImageContext(CGSizeMake(_startImageView.frame.size.width,_startImageView.frame.size.height));
 [_img drawInRect:scaledRect];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

_startImageView.image=scaledImage;

现在图像将会是:

enter image description here

原始选择的图像尺寸为640x426,未经缩放时

原始选择的图像尺寸为1536x1286,最大缩放后(使用双指缩放操作)

正如您所看到的,图像仍然没有明显变化,因为图像已经在图像视图接收图像之前被裁剪/缩放了

因此,即使您尝试执行以下操作:

      [_img drawInRect:_startImageView.frame];

图片不会按我们的需求绘制,因为选择器所提供的图片已经在编辑过程中缩放了,是经过 edited image 处理的。

解决方法:

要解决这个问题,你需要在 didFinishPickingMediaWithInfo: 方法中选择原始图片。

       info[UIImagePickerControllerOriginalImage];

这将为您提供以下图片:

输入图像描述


我也在iOS 9中使用了ImagePicker,但是是用Objective-C编写的。我认为语言并不是问题。 - Teja Nandamuri
尝试将imageViewRect设置为cgrectmake(0,0,50,50),如果它是一个iboutlet,请尝试约束其宽度和高度。 - Teja Nandamuri
我遇到了同样的问题。但为了验证问题是否出在UIImagePickerController上,我下载并稍微修改了Apple提供的一个示例 - https://developer.apple.com/library/ios/samplecode/PhotoPicker/Introduction/Intro.html。将allowsEditing设置为YES,它可以正常工作。 - Vitali Tchalov
2
更新我的上面的评论:我缩小了问题范围 - 它只与iPad有关。在PhotoPicker演示应用程序项目的Deployment Info中选择iPhone,它按预期工作。但是,当设置为iPad时,在imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info方法中返回的editedImage被裁剪到左上角。(原始图像很好)。修改示例应用程序以重现:1)在第118行后添加imagePickerController.allowsEditing = YES; - Vitali Tchalov
将以下与程序相关的内容从英语翻译成中文。仅返回已翻译的文本:将第251行替换为:UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage]; - Vitali Tchalov
显示剩余5条评论

2

这段代码与@pkc456的代码相似,只是稍微短一些。

对我来说这个很完美:

   import UIKit

   class PostImageViewController: UIViewController,    UINavigationControllerDelegate, UIImagePickerControllerDelegate {

  @IBOutlet var imageToPost: UIImageView!

   @IBAction func chooseImage(sender: AnyObject) {

    var image = UIImagePickerController()
    image.delegate = self
    image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
    image.allowsEditing = false //or true additional setup required.

    self.presentViewController(image, animated: true, completion: nil)

}

         func imagePickerController(picker: UIImagePickerController,    didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {



    self.dismissViewControllerAnimated(true, completion:nil)

}

这个能正常工作吗?


1
我正在使用Xcode 7.1(Swift)开发,并发现您的代码非常适合。我也在我的项目中编写了下面的代码,它成功地运行了。
func showPicker(){
    let type = UIImagePickerControllerSourceType.PhotoLibrary
    if(UIImagePickerController.isSourceTypeAvailable(type)){
        let pickerController = UIImagePickerController()
        pickerController.delegate = self
        pickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
        pickerController.allowsEditing = false
        self.presentViewController(pickerController, animated: true, completion: nil)
    }
}

func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
    let imageView = self.view.viewWithTag(20) as! UIImageView
    let selectedImage : UIImage = image
    imageView.image=selectedImage
    self.dismissViewControllerAnimated(true, completion: nil)
}

你的代码和我的代码唯一的区别在于ImagePickerController实例的可见性。供您参考,我上传了我的代码:- https://www.dropbox.com/s/pe0yikxsab8u848/ImagePicker-Swift.zip?dl=0 我的想法只是让您看一下我的代码,也许您会对您代码中哪个部分出现故障有所了解。

1
非常感谢您抽出时间来帮助并上传示例,但不幸的是,您的答案需要 pickerController.allowsEditing = false。我需要用户能够在 UIImagePickerController 中调整图像大小。我现在已经了解到这个问题已经向苹果报告 - 这里是链接 https://forums.developer.apple.com/thread/19999 - pete
是的,当我将allowsEditing = true时,您的问题可以重现。您在开发者论坛上发布的内容很棒。 - pkc456
不,这看起来不像是iOS 9的一个bug - 我下载并稍微修改了苹果提供的UIImagePickerController示例,网址为https://developer.apple.com/library/ios/samplecode/PhotoPicker/Introduction/Intro.html。将allowsEditing设置为YES,并修改了didFinishPickingMediaWithInfo方法以获取编辑后的图像。结果?它实际上运行良好。问题一定在我们使用它的方式上。 - Vitali Tchalov
@vitaliTchalov 苹果提供的代码也将 allowsEditing 设置为 NO。 - Groot
@VitaliTchalov 苹果提供的代码也只适用于 iPhone。如果您将项目设置为通用并在 iPad 上运行它,请将 allows editing 设置为 true 并使用编辑后的图像。这样做是无效的。 - Daniel T.

1
对我来说,问题已经解决了,显示模式为弹出窗口。
  @IBAction func photoButton(sender: AnyObject) {

    imagePicker.allowsEditing = true
    imagePicker.sourceType = .PhotoLibrary

    let controller = self.imagePicker


    controller.modalPresentationStyle = UIModalPresentationStyle.Popover
    controller.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
    let popover = controller.popoverPresentationController

    popover?.sourceView = self
    controller.preferredContentSize = CGSize(
        width: self.frame.width * 0.6,
        height: self.frame.height * 0.6
    )

    popover?.sourceRect = CGRectMake(
        CGRectGetMidX(self.bounds),
        CGRectGetMidY(self.bounds),
        0,
        0
    )


    self.presentViewController(self.imagePicker, animated: true, completion: nil)
}

1

看起来您正在使用IB和自动布局,但设置了一个右侧约束。尝试在您的故事板中添加一些约束。


不是关于限制的问题!!!它与相机选择器返回的图像有关!!! - Teja Nandamuri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接