How can I determine the largest PHAsset
image size that is available on an iOS device, where by "available" I mean currently on the device, not requiring any network download from iCloud Photo Library?
I've been developing an app where a collection of thumbnails are shown in a UICollectionView
(much like the Photos app) and then a user can select an image to see it full size. The full size image is downloaded from iCloud if necessary. However, I want to show the user the largest possible version of the image until the full size is available.
The way the Photos Framework works is rather odd:
In the collection view, I'm using a PHCachingImageManager
to cache (and later request) images with a targetSize
of 186x186 pixels (double the UICollectionViewCell
dimensions because of retina scaling).
That works very well, with very fast scrolling and no lag in filling in the cells with images. Checking the size of the images returned, they are all roughly 342x256 pixels. That's on my iPhone 6 with iCloud Photo Library enabled and 'Optimize Storage' enabled, so only small thumbnails are stored on device for most images.
However, the odd part is that if I then request the full size (or much larger) version of any image, either with PHCachingImageManager
or PHImageManager.defaultManager()
using the PHImageRequestOptionsDeliveryMode.Opportunistic
option, the first (low quality) image that is returned is a tiny 60x45 pixel postage stamp that looks horrible on the full screen, until eventually the full size image is downloaded to replace it.
Clearly there are larger thumbnails (342x256) on the device already, as they were just shown in the collection view! So why the hell doesn't it return them as the first 'low quality' image until the full size has been downloaded?? Just to make sure the 342x256 images really were already on the device I ran the code in airplane mode so no network access was happening.
What I found was that if I requested any size up to 256x256 I would get the 342x256 images returned. As soon as I went larger (even 1 pixel) it would first return me 60x45 images and then try to download the full size image.
I've changed my code to make a 256x256 request first, followed by a full size request with PHImageRequestOptionsDeliveryMode.HighQualityFormat
(which doesn't return a tiny intermediate image), and that works beautifully. It's also what the iOS Photos app must be doing as it displays relatively high quality thumbnails whilst it's downloading the full image.
So, with that background, how do I know what the largest on device image size is for a PHAsset
? Is 256x256 a magic number, or does it depend on how iCloud Photo Library is optimising for space (based on size of library and available device storage)?
Certainly seems like a bug that Photos Framework is not returning the largest image currently available (when asked for a size larger than it currently has), and that to get the largest size that it has, you have to ask for that size or smaller, because if you ask for larger, you'll get a 60x45 miniature! Bizarre.
UPDATE: Bug report submitted to Apple: https://openradar.appspot.com/25181601
Example project that demonstrates the bug: https://github.com/mluisbrown/PhotoKitBug
Using the example project posted in the question I was able to reproduce the issue in the simulator, but when I made the following change I would receive only the largest image:
let targetSize = PHImageManagerMaximumSize
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With