Pregunta

Estoy creando una aplicación de iPhone que extraer datos desde una API Web, incluyendo direcciones de correo electrónico. Me gustaría mostrar una imagen asociada a cada dirección de correo electrónico en celdas de la tabla, por lo que estoy buscando en la libreta de direcciones para las imágenes y volver a caer en una forma predeterminada si la dirección de correo electrónico no está en el libro. Esto funciona muy bien, pero tengo algunas preocupaciones:

  • Rendimiento : Las recetas que he encontrado para buscar un registro de libreta de direcciones por dirección de correo electrónico (o número de teléfono) se informa bastante lento . La razón de esto es que uno debe iterar sobre todos los registros de la libreta de direcciones, y para cada uno que tiene una imagen, iterar sobre todas las direcciones de correo electrónico para encontrar una coincidencia. Esto puede llevar mucho tiempo para un libro de direcciones grande, por supuesto.

  • Las células Tabla : Así que pensé en reunir todas las direcciones de correo electrónico para el que necesito para encontrar imágenes y encontrar todos a la vez. De esta manera me iterar a través del libro solamente una vez para todas las direcciones. Pero esto no funciona bien para las celdas de la tabla, donde cada celda corresponde a una única dirección de correo electrónico. Yo tampoco tengo que recoger todas las imágenes antes de mostrar cualquier célula (potencialmente lento), o tiene cada célula mirar hacia arriba cada imagen a medida que se carga (incluso más lento, ya que necesitaría para recorrer el libro para encontrar una coincidencia para < em> cada dirección de correo electrónico ).

  • asíncrono de búsqueda : Entonces pensé en mirar hacia arriba a granel, pero de forma asíncrona, usando NSInvocationOperation . Para cada imagen que se encuentra en la libreta de direcciones, me gustaría guardar una imagen en miniatura en el arenero aplicación. A continuación, cada célula podría simplemente hacer referencia a este archivo y mostrar el valor predeterminado si no existe (porque no está en el libro o que aún no se ha encontrado). Si la imagen se encuentra más adelante en la búsqueda asincrónica, la próxima vez que la imagen tiene que ser representada aparecería pronto. Esto podría funcionar bien para la regeneración periódica de imágenes (para cuando las imágenes se han cambiado en la libreta de direcciones, por ejemplo). Pero entonces para cualquier instancia dada de mi aplicación, una imagen puede no mostrar en realidad por un tiempo.

  • asíncrono celda de tabla de búsqueda : Idealmente, me gustaría usar algo como markjnet de celda de la tabla asíncrono actualizar para actualizar celdas de la tabla con una imagen una vez que se ha descargado. Pero para que esto funcione, tendría que desprenderse de un trabajo NSInvocationOperation para cada celda, ya que está representada y si el icono de memoria caché no se encuentra en la caja de arena. Pero entonces estamos de vuelta a la iteración de forma ineficiente a través de todo el libro de direcciones de cada uno y que puede haber un montón de ellos, si acabas de descargar un montón de nuevas direcciones de correo electrónico.

Así que mi pregunta es: ¿De qué otros hacen esto? Yo estaba jugando con Tweetie2, y parece que se actualiza celdas de la tabla se muestran de forma asíncrona. Asumo que está enviando una solicitud HTTP independiente para cada imagen que necesita. Si es así, imagino que buscando en la libreta de direcciones local por dirección de correo electrónico no es menos eficiente, por lo que tal vez es el mejor enfoque? Sólo se preocupe por los problemas de rendimiento asociados con la búsqueda de la libreta de direcciones?

Si es así, es el ahorro de una imagen en miniatura en el arenero el mejor enfoque para el almacenamiento en caché? Y si quería crear un nuevo trabajo para actualizar todas las miniaturas con cualquier cambio en la libreta de direcciones dicen una vez al día, ¿cuál es la mejor manera de hacerlo?

Como el resto de resolver este tipo de problema? Sugerencias sería muy apreciada!

¿Fue útil?

Solución

Sin importar cuál es la estrategia que utiliza para el almacenamiento en caché real de imágenes, sólo haría una sola pasada a través de los datos de la libreta de direcciones cada vez que reciba un lote de direcciones de correo electrónico, si es posible. (Y sí, me gustaría hacer esto de forma asíncrona.)

Crear una NSMutableDictionary que servirá como su caché en memoria de resultados de búsqueda. Inicializar este diccionario con cada dirección de correo electrónico de la descarga como una llave, con un centinela como el valor de esa clave (como [NSNull null]).

A continuación, iterar a través de cada ABRecordRef en la libreta de direcciones, llamando ABRecordCopyValue(record, kABPersonEmailProperty) y bucle a través de los resultados en cada ABMultiValue que se devuelve. Si cualquiera de las direcciones de correo electrónico son claves en la memoria caché, establezca [NSNumber numberWithInt:ABRecordGetRecordId(record)] como el valor de esa clave en su diccionario.

El uso de este diccionario como un índice de búsqueda, se puede obtener rápidamente las imágenes de ABRecordRefs sólo para las direcciones de correo electrónico que se está visualizando en su vista de tabla dada la posición de desplazamiento actual del usuario, como se sugiere en la respuesta de hoopjones. Puede agregar una dirección de cambio libro oyente para invalidar la caché, desencadenar otra operación de indexación, y luego actualizar la vista, si la aplicación necesita ese nivel de "arriba-a-fecha-dad".

Otros consejos

Me gustaría utilizar el último método que indicó (Asynchronous Tabla celular de búsqueda), pero sólo buscar imágenes de los registros actuales que se muestra. Sobrecargo los métodos UIScrollViewDelegate para averiguar cuándo un usuario ha dejado de desplazamiento, y sólo entonces comenzar a hacer pedidos de las celdas visibles actuales.

Algo como esto (esto se modificó ligeramente de un tutorial que encontré en la web, y que no puedo encontrar ahora, disculpas por no citar el autor):

- (void)loadContentForVisibleCells
{
    NSArray *cells = [self.table visibleCells];
    [cells retain];
    for (int i = 0; i < [cells count]; i++) 
    { 
        // Go through each cell in the array and call its loadContent method if it responds to it.
        AddressRecordTableCell *addressTableCell = (AddressRecordTableCell *)[[cells objectAtIndex: i] retain];
        [addressTableCell loadImage];
        [addressTableCell release];
        addressTableCell = nil;
    }
    [cells release];
}


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 
{
    // Method is called when the decelerating comes to a stop.
    // Pass visible cells to the cell loading function. If possible change 
    // scrollView to a pointer to your table cell to avoid compiler warnings
    [self loadContentForVisibleCells]; 
}


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
    if (!decelerate) 
    {
       [self loadContentForVisibleCells]; 
    }
}

Una vez que sepa cuál es su dirección registros son visibles actualmente, sólo hacer una búsqueda de los (5 -7 registros probablemente) será la velocidad del rayo. Una vez que agarra la imagen, simplemente almacenar en caché en un diccionario de manera que usted no tiene que volver a hacer la solicitud de la imagen más tarde.

Parece que tratar de implementar imágenes perezosos de carga en UITableView. hay un buen ejemplo de Apple, que estoy haciendo referencia aquí: perezosos en UITableView

Para su información, he publicado una biblioteca libre, potente y fácil para hacer la carga de imágenes asíncrona y almacenamiento en caché de archivos a gran velocidad: HJ Managed Objects http://www.markj.net/asynchronous-loading-caching- imágenes-iphone-hjobjman /

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top