mostrar imagen de la URL recuperada de ALAsset en iPhone

Resuelto bangdel asked hace 14 años • 4 respuestas

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;
}
bangdel avatar Oct 01 '10 14:10 bangdel
Aceptado

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 findLargeImageregresa, 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.
  • largeImagedebe 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];
        }
    };
Warren Burton avatar Oct 02 '2010 12:10 Warren Burton

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 imageWIthCGImagellamada en ese caso tiene escala y orientationse agrega cuando crea una UIImagepara 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.

oknox avatar Jan 23 '2013 23:01 oknox

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 failureBlocken nil.

Matthew Quiros avatar Sep 02 '2013 12:09 Matthew Quiros