swift phasset

swift - PHAsset a UIImage



(7)

El problema es que requestImageForAsset es un ResultHandler y este bloque de código ocurre en el futuro después de que tus funciones ya hayan impreso y devuelto el valor que esperabas. Hice cambios para mostrarte lo que está sucediendo y también sugiero algunas soluciones simples.

func getAssetThumbnail(asset: PHAsset) { var retimage = UIImage() println(retimage) let manager = PHImageManager.defaultManager() manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: nil, resultHandler: { (result, info)->Void in retimage = result println("This happens after") println(retimage) callReturnImage(retimage) // <- create this method }) println("This happens before") }

Obtenga más información sobre los cierres y el asa de finalización y los funciones asíncronas en la documentación de Apple

¡Espero que eso te ayude!

Estoy intentando crear un UIImage (como una miniatura o algo) de un PHAsset para poder pasarlo a algo que tenga un UIImage. Intenté adaptar las soluciones que encontré en SO (ya que todas las pasan directamente en una tabla de visión o algo así), pero no tengo éxito (probablemente porque no lo estoy haciendo bien).

func getAssetThumbnail(asset: PHAsset) -> UIImage { var retimage = UIImage() println(retimage) let manager = PHImageManager.defaultManager() manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: nil, resultHandler: {(result, info)->Void in retimage = result }) println(retimage) return retimage }

Los impresores me dicen que la línea manager.request no está haciendo nada ahora. ¿Cómo puedo obtener el activo como un UIImage?

Gracias.


Esto hizo lo que necesitaba que hiciera, en caso de que alguien también lo necesite.

func getAssetThumbnail(asset: PHAsset) -> UIImage { let manager = PHImageManager.defaultManager() let option = PHImageRequestOptions() var thumbnail = UIImage() option.synchronous = true manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: option, resultHandler: {(result, info)->Void in thumbnail = result! }) return thumbnail }

Editar: actualización de Swift 3

func getAssetThumbnail(asset: PHAsset) -> UIImage { let manager = PHImageManager.default() let option = PHImageRequestOptions() var thumbnail = UIImage() option.isSynchronous = true manager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in thumbnail = result! }) return thumbnail }


Para Swift 3.0.1:

func getAssetThumbnail(asset: PHAsset, size: CGFloat) -> UIImage { let retinaScale = UIScreen.main.scale let retinaSquare = CGSize(width: size * retinaScale, height: size * retinaScale)//(size * retinaScale, size * retinaScale) let cropSizeLength = min(asset.pixelWidth, asset.pixelHeight) let square = CGRect(x:0, y: 0,width: CGFloat(cropSizeLength),height: CGFloat(cropSizeLength)) let cropRect = square.applying(CGAffineTransform(scaleX: 1.0/CGFloat(asset.pixelWidth), y: 1.0/CGFloat(asset.pixelHeight))) let manager = PHImageManager.default() let options = PHImageRequestOptions() var thumbnail = UIImage() options.isSynchronous = true options.deliveryMode = .highQualityFormat options.resizeMode = .exact options.normalizedCropRect = cropRect manager.requestImage(for: asset, targetSize: retinaSquare, contentMode: .aspectFit, options: options, resultHandler: {(result, info)->Void in thumbnail = result! }) return thumbnail }

Recurso: https://gist.github.com/lvterry/f062cf9ae13bca76b0c6#file-getassetthumbnail-swift


Sugeriría usar PHCachingImageManager de Apple (que hereda de PHImageManager):

Un objeto PHCachingImageManager recupera o genera datos de imagen para activos de fotos o videos

Además, PHCachingImageManager admite un mejor mecanismo de almacenamiento en caché.

Ejemplo de obtención de una miniatura sincrónica:

let options = PHImageRequestOptions() options.deliveryMode = .HighQualityFormat options.synchronous = true // Set it to false for async callback let imageManager = PHCachingImageManager() imageManager.requestImageForAsset(YourPHAssetVar, targetSize: CGSizeMake(CGFloat(160), CGFloat(160)), contentMode: .AspectFill, options: options, resultHandler: { (resultThumbnail : UIImage?, info : [NSObject : AnyObject]?) in // Assign your thumbnail which is the *resultThumbnail* }

Además, puede utilizar PHCachingImageManager para almacenar en caché sus imágenes para una respuesta de IU más rápida:

Para usar un administrador de imágenes de almacenamiento en caché:

  1. Crea una instancia de PHCachingImageManager. (Este paso reemplaza el uso de la instancia compartida de PHImageManager).

  2. Usa los métodos de la clase PHAsset para buscar los activos que te interesan.

  3. Para preparar imágenes para esos activos, llame al método startCachingImagesForAssets: targetSize: contentMode: options: con el tamaño objetivo, el modo de contenido y las opciones que planea usar cuando solicite más adelante imágenes para cada activo individual.

  4. Cuando necesite una imagen para un activo individual, llame al método requestImageForAsset: targetSize: contentMode: options: resultHandler: y pase los mismos parámetros que utilizó al preparar ese activo.

Si la imagen que solicita está entre las ya preparadas, el objeto PHCachingImageManager devuelve inmediatamente esa imagen. De lo contrario, Fotos prepara la imagen a pedido y la almacena en la memoria caché para su uso posterior.

En nuestro ejemplo:

var phAssetArray : [PHAsset] = [] for i in 0..<assets.count { phAssetArray.append(assets[i] as! PHAsset) } let options = PHImageRequestOptions() options.deliveryMode = .Opportunistic options.synchronous = false self.imageManager.startCachingImagesForAssets(phAssetArray, targetSize: CGSizeMake(CGFloat(160), CGFloat(160)), contentMode: .AspectFill, options: options)


Swift 4.

resizeMode , deliveryMode : se pueden configurar según los requisitos del usuario.

isNetworkAccessAllowed : configure esto como "verdadero" para buscar imágenes de la nube

imageSize - tamaño de imagen requerido

func getImageFromAsset(asset:PHAsset,imageSize:CGSize, callback:@escaping (_ result:UIImage) -> Void) -> Void{ let requestOptions = PHImageRequestOptions() requestOptions.resizeMode = PHImageRequestOptionsResizeMode.fast requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.highQualityFormat requestOptions.isNetworkAccessAllowed = true requestOptions.isSynchronous = true PHImageManager.default().requestImage(for: asset, targetSize: imageSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: { (currentImage, info) in callback(currentImage!) }) }


Versión Objective-c del código basado en la respuesta dcheng.

-(UIImage *)getAssetThumbnail:(PHAsset * )asset { PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init]; options.synchronous = true; __block UIImage *image; [PHCachingImageManager.defaultManager requestImageForAsset:asset targetSize:CGSizeMake(100, 100) contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { image = result; }]; return image; }


intenta esto, me funciona, espero que te ayude también,

func getUIImage(asset: PHAsset) -> UIImage? { var img: UIImage? let manager = PHImageManager.default() let options = PHImageRequestOptions() options.version = .original options.isSynchronous = true manager.requestImageData(for: asset, options: options) { data, _, _, _ in if let data = data { img = UIImage(data: data) } } return img }