8

When I try to get an image with specific size, PHImageManager.default().requestImage is called twice with images of different sizes.

Here is the code:

static func load(from asset: PHAsset, targetSize: CGSize? = nil, completion: @escaping (UIImage?)->()) {
        let options = PHImageRequestOptions()
        options.isSynchronous = false
        let id = UUID()
        PHImageManager.default().requestImage(for: asset, targetSize: targetSize ?? PHImageManagerMaximumSize, contentMode: .aspectFill,
                options: options, resultHandler: { image, _ in
            print(id)
            runInMain {
                completion(image)
            }
        })
    }

I added UUID to check if the same UUID is printed twice.

Semyon Tikhonenko
  • 3,872
  • 6
  • 36
  • 61

3 Answers3

17

This is because the first callback returns a thumbnail while the full size image is being loaded.

From the official Apple documentation:

For an asynchronous request, Photos may call your result handler block more than once. Photos first calls the block to provide a low-quality image suitable for displaying temporarily while it prepares a high-quality image. (If low-quality image data is immediately available, the first call may occur before the method returns.) When the high-quality image is ready, Photos calls your result handler again to provide it. If the image manager has already cached the requested image at full quality, Photos calls your result handler only once. The PHImageResultIsDegradedKey key in the result handler’s info parameter indicates when Photos is providing a temporary low-quality image.

alxlives
  • 5,084
  • 4
  • 28
  • 50
9

Swift 5 It calls only one time with a .deliveryMode = .highQualityFormat

 let manager = PHImageManager.default()
 var imageRequestOptions: PHImageRequestOptions {
        let options = PHImageRequestOptions()
        options.version = .current
        options.resizeMode = .exact
        options.deliveryMode = .highQualityFormat
        options.isNetworkAccessAllowed = true
        options.isSynchronous = true
        return options
    }

  self.manager.requestImage(for: asset,targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: self.imageRequestOptions) { (thumbnail, info) in
         if let img = thumbnail {
             print(img)
          }
    }
Gurjinder Singh
  • 9,221
  • 1
  • 66
  • 58
2

Use: requestOptions.deliveryMode = .highQualityFormat

instead of: requestOptions.deliveryMode = .opportunistic

.opportunistic - Photos automatically provides one or more results in order to balance image quality and responsiveness.

Shockki
  • 61
  • 2