Определите самый большой размер изображения PHAsset, доступный на устройстве iOS

Как я могу определить самый большой PHAsset размер изображения, который доступен на устройстве iOS, где под "доступным" я подразумеваю в настоящее время на устройстве, не требуя сетевой загрузки из библиотеки фотографий iCloud?

Я разрабатывал приложение, в котором коллекция миниатюр отображается в виде UICollectionView (так же, как приложение "Фотографии"), а затем пользователь может выбрать изображение, чтобы увидеть его в полном размере. Полноразмерное изображение загружается из iCloud при необходимости. Тем не менее, я хочу показать пользователю максимально возможную версию изображения, пока не будет доступен полный размер.

Принцип работы Photos Framework довольно странный:

В представлении коллекции я использую PHCachingImageManager кэшировать (и позже запрашивать) изображения с targetSize 186x186 пикселей (удвоить UICollectionViewCell размеры из-за масштабирования сетчатки).

Это работает очень хорошо, с очень быстрой прокруткой и без задержки при заполнении ячеек изображениями. Проверяя размер возвращаемых изображений, они все примерно 342х256 пикселей. Это на моем iPhone 6 с включенной библиотекой фотографий iCloud и включенной функцией "Оптимизировать хранилище", поэтому для большинства изображений на устройстве хранятся только небольшие эскизы.

Однако странная часть заключается в том, что если я затем запрашиваю полноразмерную (или намного большую) версию любого изображения, либо PHCachingImageManager или же PHImageManager.defaultManager() с использованием PHImageRequestOptionsDeliveryMode.Opportunistic вариант, первое (низкокачественное) возвращаемое изображение представляет собой крошечную почтовую марку размером 60x45 пикселей, которая выглядит ужасно на полном экране, пока в конечном итоге для ее замены не будет загружено полноразмерное изображение.

Очевидно, что на устройстве уже есть большие эскизы (342x256), так как они только что отображались в виде коллекции! Так почему, черт возьми, он не возвращает их в качестве первого изображения "низкого качества", пока не будет загружен полный размер? Просто для того, чтобы убедиться, что изображения 342x256 действительно были на устройстве, я запустил код в режиме полета, чтобы не было доступа к сети.

Я обнаружил, что, если бы я запросил любой размер до 256x256, я бы получил изображения размером 342x256. Как только я увеличу размер (даже на 1 пиксель), он сначала вернет мне изображения размером 60x45, а затем попытается загрузить полноразмерное изображение.

Я изменил свой код, чтобы сначала выполнить запрос 256x256, а затем запрос в полном размере с PHImageRequestOptionsDeliveryMode.HighQualityFormat (который не возвращает крошечное промежуточное изображение), и это прекрасно работает. Это также то, что должно делать приложение iOS Photos, так как оно отображает миниатюры относительно высокого качества, загружая полное изображение.

Итак, с этим фоном, как я могу узнать, какой самый большой размер изображения устройства для PHAsset? Является ли 256x256 магическим числом или это зависит от того, как iCloud Photo Library оптимизирует пространство (в зависимости от размера библиотеки и доступного хранилища устройства)?

Конечно, похоже на ошибку, что Photos Framework не возвращает наибольшее доступное изображение (когда запрашивается размер больше, чем у него есть в настоящее время), и что для получения наибольшего размера вы должны запросить этот размер или меньше, потому что если вы попросите больше, вы получите миниатюру 60х45! Bizarre.

ОБНОВЛЕНИЕ: Сообщение об ошибке отправлено в Apple: https://openradar.appspot.com/25181601
Пример проекта, который демонстрирует ошибку: https://github.com/mluisbrown/PhotoKitBug

3 ответа

Используя пример проекта, размещенный в вопросе, я смог воспроизвести проблему в симуляторе, но, сделав следующее изменение, я получу только самое большое изображение:

let targetSize = PHImageManagerMaximumSize

На самом деле я не знаю причину, по которой Apple вернула бы ухудшенное изображение 45*60 с PHImageResultIsDegradedKey=1. Для меня я просто запрашиваю 256*256 изображений с deliveryMode PHImageRequestOptionsDeliveryModeHighQualityFormat, а затем использую другие PHImageRequestOptions для запроса полноразмерного изображения, как показано ниже:

PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){
// code to update the iCloud download progress
});

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// code to update UIImageView or something else.
});

И я думаю, Instagram может использовать это аналогичное решение для обработки изображений из iCloud.

[imageManager requestImageForAsset:asset
              targetSize: PHImageManagerMaximumSize
              contentMode:PHImageContentModeAspectFill
              options:nil
resultHandler:^(UIImage *result, NSDictionary *info)
{
    result;
}];
Другие вопросы по тегам