Как определить, не полностью ли загружен PHASset из iCloud (поэтому мне нужно снова запросить параметры options.networkAccessAllowed)
В документах говорится:
PHImageResultIsInCloudKey: Логическое значение, указывающее, хранятся ли данные фотоактивности на локальном устройстве или должны быть загружены из iCloud. (NSNumber) Если ДА, изображение не было предоставлено, поскольку данные о ресурсе должны быть загружены из iCloud. Чтобы загрузить данные, отправьте другой запрос и укажите YES для параметра networkAccessAllowed.
Но этот ключ всегда есть, когда ресурс хранится в iCloud Photo Library, даже если он уже полностью загружен на устройство (скачал его в моем приложении, также открыл его в приложении "Фото" ).
Если изображение недоступно, я хочу дать пользователю возможность его загрузить (но не делайте этого автоматически, по крайней мере, когда нет Wifi).
Итак, как мне узнать, нужно ли загружать изображение?
Еще более любопытно: когда мой результирующий блок
requestImageForAsset:targetSize:contentMode:options:resultHandler:
вызывается для изображения, которое нужно загрузить, я получаю последний вызов с запросомImage == nil после того, как была поставлена меньшая и деградированная версия.
В этом случае ухудшение равно NO, даже если у меня нет изображения, и изображение все равно должно быть загружено из iCloud, так как только небольшое уменьшенное изображение из приложения "Фотографии" доступно локально до сих пор.
Я тестировал это на iPhones и iPads с разными версиями iOS 8 (8.1.x, 8.2 beta, 8.3 beta), поведение всегда одно и то же.
Как только я открыл изображение в приложении "Фото", последний вызов обработчика результатов имеет полноразмерный образ, но PHImageResultIsInCloudKey все равно будет YES.
Вот некоторый код, как я запрашиваю изображения:
PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
options.networkAccessAllowed = NO;
[self.imageManager requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *requestedImage, NSDictionary *info) {
// Checking for requestedImage and the info keys here
// When a full sized image was loaded, the result of PHImageResultIsInCloudKey is still YES
// When a full sized image couldn't be loaded cause it in the cloud, isDegraded is NO and PHImageResultIsInCloudKey is YES (as always) and requestedImage is nil
}];
Ответы
Ответ 1
Я могу подтвердить, что PHImageResultIsInCloudKey не является надежным. Для изображений, хранящихся в iCloud, он возвращает 1, даже если исходное изображение было загружено на устройство. Такое поведение отличается от документации, и я предлагаю сообщить об ошибке на сайте radar.apple.com. PhotoKit, на мой взгляд, все еще очень незрелая структура - в ней много проблем, а также некоторые странные концептуальные решения.
Ответ 2
Если вы вызываете requestImageDataForAsset:
с networkAccessAllowed
, установленным в NO
, возвращаемый imageData
будет nil
, если клип еще не загружен из iCloud. В противном случае он вернет фактические данные, даже если клип сохранен в iCloud.
PHImageManager *manager = [PHImageManager defaultManager];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.networkAccessAllowed = NO;
[manager
requestImageDataForAsset:asset
options:options
resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
if ([[info valueForKey:PHImageResultIsInCloudKey] boolValue]) {
// Image is in iCloud
if (imageData) {
// Image is downloaded
} else {
// Image is not downloaded
}
}
}];
Ответ 3
Вы можете использовать progressHandler, чтобы проверить, является ли PHASset от iCloud.
__block BOOL isPhotoInICloud = NO;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){
isPhotoInICloud = YES;
// some code to update the download progress
});
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.synchronous = NO;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// use the options to get the high quality image for only once time.
});