UIImagePickerControllerOriginalImage is not working in ios 11.2.1

10,291

Solution 1

I ended up using this:

import Photos

extension UIImage {
    static func from(info: [String : Any]) -> UIImage? {
        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
            return image
        }

        var imageToBeReturned: UIImage?
        if let url = info[UIImagePickerControllerReferenceURL] as? URL,
            let asset = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil).firstObject {
            let manager = PHImageManager.default()
            let option = PHImageRequestOptions()
            option.isSynchronous = true
            manager.requestImage(for: asset, targetSize: CGSize(width: 1000, height: 1000), contentMode: .aspectFit, options: option, resultHandler: {(image: UIImage?, info: [AnyHashable : Any]?) in
                imageToBeReturned = image
            })
        }
        return imageToBeReturned
    }
}

In this way-

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let selectedImage = UIImage.from(info: info) {
        // I am happy :)
    } else {
        // I am sad :(
    }
    dismiss(animated: true, completion: nil)
}

This is working for me, please do suggest any improvements :)

Solution 2

changed in IOS 12

  image.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage

Solution 3

I've read it in a Apple Developer Forum thread that, if the image size is larger (Above 2048 X 2048) on iOS 11 UIImagePickerControllerOriginalImage returns nil. As a work-around the post suggests to use Photos framework to get the picked image. The solution offered in that post is as follows:

Objective C:

__block UIImage *image = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];  
if (@available(iOS 11.0, *))  
{   
    PHAsset * asset = (PHAsset*)[info objectForKey:UIImagePickerControllerPHAsset];  
    PHImageManager *manager = [PHImageManager defaultManager];  
    PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];  
    requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;  
    requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;  
    requestOptions.synchronous = true;  
    [manager requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:requestOptions resultHandler:^void(UIImage *img, NSDictionary *info) {  
       if(img != nil)  
       {  
          image = img;  
       }  
    }];  
}

Reference : iOS 11 does not return the original image for large images with UIImagePickerControllerOriginalImage

Swift:

var image = info[UIImagePickerControllerOriginalImage]
if #available(iOS 11.0, *)
{
    let asset                    = info[UIImagePickerControllerPHAsset] as! PHAsset
    let manager                  = PHImageManager.default()
    let requestOptions           = PHImageRequestOptions()
    requestOptions.resizeMode    = PHImageRequestOptionsResizeMode.exact
    requestOptions.deliveryMode  = PHImageRequestOptionsDeliveryMode.highQualityFormat
    requestOptions.isSynchronous = true
    manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: { (img, info) in
        if img != nil
        {
            image = img
        }
    })
}

Solution 4

the method signature has changed like so:

  func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    guard let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else {
        fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
    }

    // Set photoImageView to display the selected image.
    photoImageView.image = selectedImage

    // Dismiss the picker.
    dismiss(animated: true, completion: nil)
}

Note the second argument:

didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]

It is not an array of strings like in the previous method signature.

Share:
10,291
Nikhil Manapure
Author by

Nikhil Manapure

Hey, I wonder how I made it to top 10 Swift developers (on SO) in Mumbai. My Medium Blogs. My LinkedIn Profile. My Github Profile. My Website. #GiveBack #SOReadyToHelp #HappyToHelp

Updated on June 08, 2022

Comments

  • Nikhil Manapure
    Nikhil Manapure almost 2 years

    In what cases will I be sad? if I have set allowEditing as false.

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
            // I am happy :)
        } else {
            // I am sad :(
        }
        dismiss(animated: true, completion: nil)
    }
    

    (I got a crash in iOS 11.2.1 iPhone SE(as per Crashlytics), so confused if there are legit conditions where this can fail or it is just an iOS bug.)

  • Camilo Aguilar
    Camilo Aguilar almost 6 years
    @Midhun what could be a possible scenario to get img==nil?
  • Midhun MP
    Midhun MP almost 6 years
    @CamiloAguilar: One situation is like, you have saved the asset url and deleted the image then requested the image using deleted url. The image will be nil in this case.
  • Evan
    Evan over 3 years
    I got nil for original image. And this works for me.