Lo que quiere estar al tanto de cuando se mezclan desincronizado y tablas es que el asynch termina en un momento desconocido en el futuro, posiblemente después de la célula se desplaza instante, sacado, reutilizados, etc.
Además, la imagen que se extrae de la web se pierde si esa celda se desplaza. No estoy seguro si AFNetworking almacena en caché, pero podría ser mejor no asumirlo. He aquí una solución utilizando una red nativa:
// ...
NSDictionary *post = [posts objectAtIndex:indexPath.row];
NSString *postpictureUrl = [post objectForKey:@"picture"];
// find a place in your model, or add one, to cache an actual downloaded image
UIImage *postImage = [post objectForKey:@"picture_image"];
if (postImage) {
cell.imageView.image = postImage; // this is the best scenario: cached image
} else {
// notice how we don't pass the cell - we don't trust its value past this turn of the run loop
[self asynchLoad:postpictureUrl forIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:@"default"];
}
// ...
Ahora, una carga asynch sin sentido y sin ninguna ayuda tercera parte
- (void)asynchLoad:(NSString *)urlString forIndexPath:(NSIndexPath *)indexPath {
NSURL *url = [NSURL urlWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error) {
// create the image
UIImage *image = [UIImage imageWithData:data];
// cache the image
NSDictionary *post = [posts objectAtIndex:indexPath.row];
[post setObject:image forKey:@"picture_image"];
// important part - we make no assumption about the state of the table at this point
// find out if our original index path is visible, then update it, taking
// advantage of the cached image (and a bonus option row animation)
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
if ([visiblePaths containsObject:indexPath]) {
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation: UITableViewRowAnimationFade];
// because we cached the image, cellForRow... will see it and run fast
}
}
}];
}
Para que esto funcione, los mensajes deben ser creados como NSMutableDictionary ...
// someplace in your code you add a post to the posts array. do this instead.
NSDictionary *postData = // however you get a new post
[posts addObject:[NSMutableDictionary dictionaryWithDictionary:postData]];
Alternativamente, si es difícil cambiar el modelo de mensajes directamente, puede configurar otra estructura para almacenar en caché las imágenes descargadas. Un diccionario mutable introducido por las cadenas de URL es una buena estructura de empleo:
@property (nonatomic,strong) NSMutableDictionary *imageCache;
@synthesize imageCache=_imageCache;
// lazy init on the getter...
- (NSMutableDictionary *)imageCache {
if (!_imageCache) {
_imageCache = [NSMutableDictionary dictionary];
}
return _imageCache;
}
Ahora, cuando la configuración de la célula, a ver si hay una imagen almacenada en caché mediante la comprobación de la memoria caché ...
// change to the cellForRowAtIndexPath method
NSString *postpictureUrl = [post objectForKey:@"picture"];
UIImage *postImage = [self.imageCache valueForKey:postpictureUrl];
Y una vez que se descarga una imagen, en caché ...
// change to the asynchLoad: method I suggested
UIImage *image = [UIImage imageWithData:data];
[self.imageCache setValue:image forKey:urlString];
@carlveazy ¿hay alguna forma de solucionar este problema de tamaño utilizando AFNetworking? – pepe
No estoy seguro con AFNetworking, pero probablemente tendrá que implementar la devolución de llamada exitosa desde su categoría 'UIImageView' y asegurarse de que la celda reciba' setNeedsLayout' una vez que la imagen se actualice. Además, tendrás que asegurarte de que la reutilización de las células no se interponga aquí, lo que puede ser complicado, pero supongo que es un problema aparte. –
Parece que hay una opción aquí, pero no estoy seguro si esto resuelve lo que estás sugiriendo - http://afnetworking.github.com/AFNetworking/Categories/UIImageView+AFNetworking.html – pepe