Определите самый большой размер изображения 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;
}];