2012-05-17 15 views
10

Parte de mi aplicación tiene un navegador de fotos, algo similar a la aplicación de fotos de Apple, con un controlador de vista inicial para buscar miniaturas de fotos y una vista detallada que se muestra al tocar una foto.ALAssetsLibrary - bloqueo después de recibir ALAssetsLibraryChangedNotification

Estoy usando ALAssetsLibrary para acceder a las fotos, y paso una serie de URL ALAsset a mi controlador de vista detallada para que pueda pasar de una foto a la siguiente.

Todo funciona muy bien, hasta que reciba una ALAssetsLibraryChangedNotification durante el escaneo de una fotografía a otra (en el controlador de la vista de detalle), que a menudo resulta en un accidente:

NOTIFICACIÓN: la biblioteca de activos cambió mi // NSLog propia para cuando se produce la notificación

activos de carga ... // mi propia NSLog para cuando empiece a recargar activos en el navegador de miniaturas

aserción: (tamaño == BytesRead), la función - [ALAssetRepresentation _imageData], presentar /SourceCache/AssetsLibrary/MobileSlideShow-1373.58.1/Sources/ALAssetRepresentation.m, línea 224.

La línea de código específica de que se estrelle en adelante, es en llamando [metadatos currentRep] como se muestra aquí:

- (void)someMethod { 
     NSURL *assetURL = [self.assetURLsArray objectAtIndex:index]; 
     ALAsset *currentAsset; 

     [self.assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) { 

      [self performSelectorInBackground:@selector(configureDetailViewForAsset:) withObject:asset]; 

      } failureBlock:^(NSError *error) { 
        NSLog(@"failed to retrieve asset: %@", error); 
     }]; 
} 

- (void)configureDetailViewForAsset:(ALAsset *)currentAsset { 
    ALAssetRepresentation *currentRep = [currentAsset defaultRepresentation]; 

    if (currentAsset != nil) { 
     // do some stuff 
    } 
    else { 
     NSLog(@"ERROR: currentAsset is nil"); 
    } 

    NSDictionary *metaDictionary; 
    if (currentRep != nil) { 
     metaDictionary = [currentRep metadata]; 

     // do some other stuff 
    } 
    else { 
     NSLog(@"ERROR: currentRep is nil"); 
    } 
} 

entiendo que una vez que se recibe una notificación, que invalida cualquier referencia a objetos ALAsset y ALAssetRepresentation ... pero ¿cómo se supone que voy a hacer frente a la situación en la que invalida algo justo en el medio de intentar acceder?

He tratado de establecer un BOOL, justo cuando se recibe la notificación de abortar por completo y bloquear [currentRep metadatos] que alguna vez se llamó, pero incluso eso no coge cada vez:

if (self.receivedLibraryChangeNotification) { 
    NSLog(@"received library change notification, need to abort"); 
} 
else { 
    metaDictionary = [currentRep metadata]; 
} 

Es hay algo que pueda hacer? En este punto, estoy casi listo para abandonar el uso del marco ALAssetsLibrary.

(nota de este hilo sin resolver en los foros dev de Apple que describen el mismo problema: https://devforums.apple.com/message/604430)

Respuesta

6

Parece que el problema está aquí:

[self.assetsLibrary assetForURL:nextURL 

    resultBlock:^(ALAsset *asset) { 
     // You should do some stuff with asset at this scope 
     ALAssetRepresentation *currentRep = [asset defaultRepresentation]; 
     // Assume we have a property for that 
     self.assetRepresentationMetadata = [currentRep metadata]; 
     ... 
     // assume we have a method for that 
     [self updateAssetDetailsView]; 
    } 

    failureBlock:^(NSError *error) { 
     NSLog(@"failed to retrieve asset: %@", error); 
    }]; 

Una vez que tenga activo usuario es mejor copie la información de los activos proporcionándoles los datos necesarios en las subvistas de los controladores de detalles o guardándolos en caché para usarlos en el futuro. Puede ser útil para evitar problemas de invalidación de ALAsset. Cuando se envía la notificación ALAssetsLibraryChangedNotification, es posible que deba descartar los detalles del controlador y consultar el contenido de la biblioteca desde el principio.

+1

Tengo que hacer más pruebas ... pero eso puede haber ayudado. No se muestra en mi código anterior (ya que quería simplificarlo para publicar aquí), pero se estaba llamando a [metadatos currentRep] en una cadena de fondo. Lo cambié para recuperar el diccionario de metadatos dentro del resultado resultFlock "assetForURL" como sugeriste, que está en el hilo principal. Hasta ahora no se ha bloqueado ... ¿quizás el método de metadatos de ALAssetRepresentation no es seguro para subprocesos? –

+0

Lo más importante aquí es que lleva tiempo obtener medios con 'assetForURL'. Por lo tanto, fuera del bloque de finalización no puede estar seguro de que haya descargado los medios ... – voromax

+0

Actualicé mi pregunta para mostrar con precisión cómo estaba llamando al método de "metadatos" en un hilo de fondo. En función de su respuesta, la cambié para que recuperara primero el diccionario de metadatos y luego pasara eso y el activo a mi método configureDetailView. De nuevo, necesito hacer más pruebas, pero hasta ahora todo bien ... –

Cuestiones relacionadas