Determine el tamaño de imagen PHAsset más grande disponible en el dispositivo iOS
photokit icloud-photo-library (3)
¿Cómo puedo determinar el tamaño de imagen PHAsset
más grande que está disponible en un dispositivo iOS, donde "disponible" significa que actualmente estoy en el dispositivo y no requiere ninguna descarga de red desde iCloud Photo Library?
He estado desarrollando una aplicación donde se muestra una colección de miniaturas en una UICollectionView
(como la aplicación Fotos) y luego un usuario puede seleccionar una imagen para verla en tamaño completo. La imagen de tamaño completo se descarga desde iCloud si es necesario. Sin embargo, quiero mostrar al usuario la versión más grande posible de la imagen hasta que esté disponible el tamaño completo.
La forma en que funciona el Marco de Fotos es bastante extraña:
En la vista de colección, estoy usando un PHCachingImageManager
para cache en cache (y luego request ) imágenes con un targetSize
de destino de 186x186 píxeles (doble las dimensiones de UICollectionViewCell
debido a la escala de retina).
Eso funciona muy bien, con un desplazamiento muy rápido y sin retraso en rellenar las celdas con imágenes. Al verificar el tamaño de las imágenes devueltas, todas son aproximadamente 342x256 píxeles. Eso está en mi iPhone 6 con iCloud Photo Library habilitado y ''Optimizar almacenamiento'' habilitado, por lo que solo se almacenan miniaturas pequeñas en el dispositivo para la mayoría de las imágenes.
Sin embargo, la parte impar es que si luego solicito la versión de tamaño completo (o mucho más grande) de cualquier imagen, ya sea con PHCachingImageManager
o PHImageManager.defaultManager()
usando la PHImageRequestOptionsDeliveryMode.Opportunistic
, la primera imagen (baja calidad) que se devuelve es un pequeño sello de 60x45 píxeles que se ve horrible en la pantalla completa, hasta que finalmente se descarga la imagen de tamaño completo para reemplazarla.
Claramente, ya hay miniaturas más grandes (342x256) en el dispositivo, ¡como se mostraron en la vista de colección! Entonces, ¿por qué diablos no los devuelve como la primera imagen de "baja calidad" hasta que se descarga el tamaño completo? Solo para asegurarme de que las imágenes 342x256 realmente ya estaban en el dispositivo, ejecuté el código en modo avión para que no ocurriera el acceso a la red.
Lo que encontré fue que si solicito cualquier tamaño de hasta 256x256 obtendría las imágenes de 342x256 devueltas. Tan pronto como fui más grande (incluso 1 píxel) primero me devolvería 60x45 imágenes y luego intentaría descargar la imagen a tamaño completo.
He cambiado mi código para hacer una solicitud de 256x256 primero, seguido de una solicitud de tamaño completo con PHImageRequestOptionsDeliveryMode.HighQualityFormat
(que no devuelve una pequeña imagen intermedia), y funciona a la perfección. También es lo que debe hacer la aplicación iOS Photos, ya que muestra miniaturas de calidad relativamente alta mientras descarga la imagen completa.
Entonces, con ese fondo, ¿cómo puedo saber cuál es el tamaño más grande de la imagen del dispositivo para un PHAsset
? ¿Es 256x256 un número mágico, o depende de cómo iCloud Photo Library se está optimizando para el espacio (según el tamaño de la biblioteca y el almacenamiento disponible del dispositivo)?
Ciertamente, parece ser un error que Photos Framework no devuelve la imagen más grande actualmente disponible (cuando se le solicita un tamaño más grande que el que tiene actualmente), y que para obtener el tamaño más grande que tiene, debe solicitar ese tamaño o más pequeño, ¡Porque si pides más grande, obtendrás una miniatura de 60x45! Extraño.
ACTUALIZACIÓN: Informe de error enviado a Apple: https://openradar.appspot.com/25181601
Proyecto de ejemplo que demuestra el error: https://github.com/mluisbrown/PhotoKitBug
Al usar el proyecto de ejemplo publicado en la pregunta, pude reproducir el problema en el simulador, pero cuando hiciera el siguiente cambio solo recibiría la imagen más grande:
let targetSize = PHImageManagerMaximumSize
En realidad no sé la razón por la que Apple devolvería la imagen degradada de 45 * 60 con PHImageResultIsDegradedKey = 1. Para mí, solo solicito la imagen 256 * 256 con deliveryMode PHImageRequestOptionsDeliveryModeHighQualityFormat al principio, luego uso las otras PHImageRequestOptions para solicitar una imagen a tamaño completo como la siguiente:
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.
});
Y creo que Instagram puede usar esta solución similar para manejar la imagen de iCloud.
[imageManager requestImageForAsset:asset
targetSize: PHImageManagerMaximumSize
contentMode:PHImageContentModeAspectFill
options:nil
resultHandler:^(UIImage *result, NSDictionary *info)
{
result;
}];