17

After update to iOS 11, photo assets now load slowly and I get this message in console:

[ImageManager] Unable to load image data, /var/mobile/Media/DCIM/103APPLE/IMG_3064.JPG

I use static function to load image:

class func getAssetImage(asset: PHAsset, size: CGSize = CGSize.zero) -> UIImage? {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.isSynchronous = true

    var assetImage: UIImage!
    var scaleSize = size
    if size == CGSize.zero {
        scaleSize = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
    }

    manager.requestImage(for: asset, targetSize: scaleSize, contentMode: .aspectFit, options: option) { (image, nil) in
        if let image = image {
            assetImage = image
        }
    }
    if assetImage == nil {
        manager.requestImageData(for: asset, options: option, resultHandler: { (data, _, orientation, _) in
            if let data = data {
                if let image = UIImage.init(data: data) {
                    assetImage = image
                }
            }
        })
    }
    return assetImage
}

Request image for asset usually always succeeds, but it prints this message. If I use requestImageData function only, there is no such message, but photos made with Apple camera lose their orientation and I get even more issues while loading big amount of images (I use image slideshow in my app).

Apple always sucks when it comes to updates, maybe someone got a solution how to fix this? It even fails to load an asset, when there is a big list of them in user camera. Switching to requestImageData is not an option for me as it brings nil data frequently now.

I would like to point out, that I call this function only once. It is not used in UITableView etc. I use other code for thumbs with globally initialised manager and options, so assets are definitely not nil or etc. I call this function only when user clicks at certain thumb. When gallery has like 5000 photos, maybe connection to assets is just overloaded and later it can't handle request and crashes? So many questions.

Bio-Matic
  • 717
  • 8
  • 19

5 Answers5

10

Hey I was having the warning as well and here is what worked for me.

Replacing CGSize(width: asset.pixelWidth, height: asset.pixelHeight) by PHImageManagerMaximumSize in requestImage call removed the warning log

Hope this helps,

sachadso
  • 789
  • 7
  • 10
  • And now you’re receiving a big memory-wasting image that you don’t need and don’t want. Why is that a solution to anything? I’d rather see the warning (and ignore it). – matt Oct 05 '18 at 13:20
6

I had the same problem. Though this did not completely solve it, but it definitely helped.

option.isNetworkAccessAllowed = true

This helps only on the devices where Optimise iPhone Storage option for Photos app has been turned on.

Mitul Jindal
  • 550
  • 3
  • 14
  • 1
    For me it did not work, because I also use iCloud photos in my device. It is probably OS related bug. – Bio-Matic Mar 28 '18 at 10:23
  • 1
    Thanks! Fixed a bug that I was hunting the whole day which only occurred on only one iPhone. – Apfelsaft Aug 26 '18 at 14:19
  • Thanks. It works. I also had to set the option option.version = .original to load the image in the original size and not just the thumbnail. – Mikiko Jane Feb 29 '20 at 08:50
2

Your code has some serious issues. You are saying .isSynchronous = true without stepping into a background thread to do the fetch. That is illegal and is what is causing the slowness. Plus, you are asking for a targetSize without also saying .resizeMode = .exact, which means you are getting much bigger images than you are asking for.

However, the warning you're seeing is irrelevant and can be ignored. It in no way signals a failure of image delivery; it seems to be just some internal message that has trickled up to the console by mistake.

matt
  • 447,615
  • 74
  • 748
  • 977
  • This exact code was used to get full size images. And this function itself has been called from the background threads. – Bio-Matic Aug 12 '18 at 07:23
  • The point of my answer is that the warning is not your bug. The images arrive, so ignore the warning. – matt Aug 12 '18 at 10:36
0

This seems to be a bug with iOS 11, but I found I could work around by setting synchronous option false. I reworked my code to deal with the async delivery. Probably you can use sync(execute:) for quick fix.

Also, I believe the problem only occurred with photos delivered by iCloud sharing.

user1055568
  • 1,191
  • 11
  • 19
  • 4
    It did not work for me. However it seems that optimising calls to Photos framework increased overall performance. Now I fetch assets OperationQueue and later I set them async on UI items. I have disabled network photos, so they are definitely not in the iCloud and sync/async works pretty much the same for me. It seems that it is yet another iOS bug, now assets work much slower than before. – Bio-Matic Sep 25 '17 at 14:50
  • 1
    I believe that async did not work for me at first either, though I can't remember what I changed to make it work. What is working now is setting deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic, contentMode PHImageContentModeAspectFill. The log message will still appear but full size image eventually arrives. – user1055568 Sep 26 '17 at 19:03
0

You can try method "requestImageData" with following options. This worked for me in iOS 11.2 (both on device and simulator).

let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.resizeMode = .exact
options.isSynchronous = true

PHImageManager.default().requestImageData(for: asset, options: options, resultHandler: { (data, dataUTI, orientation, info) in
Hitesh
  • 51
  • 3
  • 7
  • 1
    Synchronous image requests will block the main thread if not done on a background thread – Josh Bernfeld Mar 16 '18 at 06:09
  • @thedeveloper3124 In my case user is waiting for the image after selection, so used this synchronously. Asynchronously, is taking too much time or not seems to be giving image. – Hitesh Mar 17 '18 at 06:17