mostrar imagen de la URL recuperada de ALAsset en iPhone
Estoy usando ALAsset Framework para acceder a los archivos en la galería de fotos del dispositivo.
Hasta ahora puedo acceder a la miniatura y mostrarla.
Quiero mostrar la imagen real en una vista de imagen pero no puedo entender cómo hacerlo.
Intenté usar el campo URL en el objeto ALAsset pero no tuve éxito.
¿Alguien sabe cómo se puede hacer esto?
Aquí hay un código donde pude acceder a la miniatura y colocarla en una celda de la tabla:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
//here 'asset' represents the ALAsset object
asset = [assets objectAtIndex:indexPath.row];
//i am accessing the thumbnail here
[cell.imageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];
[cell.textLabel setText:[NSString stringWithFormat:@"Photo %d", indexPath.row+1]];
return cell;
}
La API ha cambiado ligeramente las reglas y ya no obtienes acceso directo al sistema de archivos de la biblioteca de iPhoto. En su lugar, obtienes URL de biblioteca de activos como esta.
assets-library://asset/asset.JPG?id=1000000003&ext=JPG
Utilice el objeto ALAssetLibrary para acceder al objeto ALAsset a través de la URL.
entonces, desde los documentos de ALAssetLibrary, coloque esto en un encabezado (o en su fuente)
typedef void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *asset);
typedef void (^ALAssetsLibraryAccessFailureBlock)(NSError *error);
lo cual no es estrictamente necesario pero mantiene las cosas bonitas.
y luego en tu fuente.
-(void)findLargeImage
{
NSString *mediaurl = [self.node valueForKey:kVMMediaURL];
//
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref) {
largeimage = [UIImage imageWithCGImage:iref];
[largeimage retain];
}
};
//
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(@"booya, cant get image - %@",[myerror localizedDescription]);
};
if(mediaurl && [mediaurl length] && ![[mediaurl pathExtension] isEqualToString:AUDIO_EXTENSION])
{
[largeimage release];
NSURL *asseturl = [NSURL URLWithString:mediaurl];
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:asseturl
resultBlock:resultblock
failureBlock:failureblock];
}
}
Un par de cosas a tener en cuenta es que esto utiliza bloques que eran nuevos para mí antes de comenzar a migrar iOS4, pero es posible que desees consultarlos.
https://www.mikeash.com/pyblog/friday-qa-2008-12-26.html
y
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html
Te inclinan un poco la cabeza, pero si piensas en ellos como selectores de notificaciones o devoluciones de llamadas, es de alguna ayuda.
También
- cuando
findLargeImage
regresa, el bloque de resultados aún no se habrá ejecutado ya que es una devolución de llamada. Por lo tanto, la imagen grande aún no será válida. largeImage
debe ser una variable de instancia que no tenga como ámbito el método.
Utilizo esta construcción para hacer esto cuando uso el método, pero es posible que encuentre algo más adecuado para su uso.
[node.view findLargeImage];
UIImage *thumb = node.view.largeImage;
if (thumb) { blah blah }
Eso es lo que aprendí al intentar que esto funcionara de todos modos.
actualización de iOS 5
Cuando se activa el bloque de resultados, parece ser un poco más lento con iOS5 y tal vez con dispositivos de un solo núcleo, por lo que no podía confiar en que la imagen estuviera disponible directamente después de llamar findLargeImage
. Entonces lo cambié para llamar a un delegado.
@protocol HiresImageDelegate <NSObject>
@optional
-(void)hiresImageAvailable:(UIImage *)aimage;
@end
y ven cá
//
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref) {
UIImage *largeimage = [UIImage imageWithCGImage:iref];
[delegate hiresImageAvailable:large];
}
};
La respuesta de Warren funcionó bien para mí. Una cosa útil para algunas personas es incluir los metadatos de orientación y escala de la imagen al mismo tiempo. Haz esto en tu bloque de resultados de esta manera:
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref)
{
UIImage *largeimage = [UIImage imageWithCGImage:iref scale:[rep scale] orientation:[rep orientation]];
[delegate hiresImageAvailable:large];
}
};
La imageWIthCGImage
llamada en ese caso tiene escala y orientation
se agrega cuando crea una UIImage
para usted.
[UIImage imageWithCGImage:iref scale:[rep scale] orientation:[rep orientation]];
Un truco a tener en cuenta es que si usas [rep fullScreenImage]
en lugar de [rep fullResolutionImage]
iOS 5 obtendrás una imagen que ya está girada; sin embargo, tiene la resolución de la pantalla del iPhone, es decir, tiene una resolución más baja.
Solo para combinar las respuestas de Warren y Oknox en un fragmento más corto:
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary assetForURL:self.selectedPhotos[i] resultBlock: ^(ALAsset *asset){
ALAssetRepresentation *representation = [asset defaultRepresentation];
CGImageRef imageRef = [representation fullResolutionImage];
if (imageRef) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.image = [UIImage imageWithCGImage:imageRef scale:representation.scale orientation:representation.orientation];
// ...
}
} failureBlock: ^{
// Handle failure.
}];
Personalmente me gusta configurar mi failureBlock
en nil
.