ios - El desplazamiento de UITableView no es uniforme
uiimage xamarin (6)
No tengo suficiente representante para comentar, así que aquí hay una respuesta que ayudó a mi rendimiento de desplazamiento de tabla:
- Haga que la altura de la vista de tabla sea mayor que la ventana visible. Las celdas se cargarán "fuera de pantalla" y ayudarán a mejorar la suavidad de desplazamiento.
- Haga su procesamiento de imágenes con el siguiente método:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
Esos dos trucos hicieron que mi mesa fluyera realmente bien. Obtengo mis datos de imagen de un servicio de API y AFNETWORKING tiene un increíble cargador de imágenes, pero no es necesario porque las imágenes están en el paquete.
Tengo el problema de desplazamiento suave en mi UITableView con UITableViewCell que contiene UIImageView. Se pueden encontrar problemas similares en todo el StrackOverflow, pero ninguna de las soluciones propuestas me ayudó a deshacerme por completo del desfase.
Mi caso es bastante común:
- las imágenes se almacenan en el almacenamiento de la aplicación (en mi muestra en el paquete de la aplicación)
- las imágenes pueden tener diferentes tamaños (500x500, 1000x1000, 1500x1500)
- Necesito mostrar esas imágenes en UITableView donde el tamaño de UIImageView es 120x120 (retina)
Seguí múltiples consejos de optimización y logré optimizar mucho el desplazamiento. Lamentablemente todavía no es perfecto. Esta es mi situación:
- primero moví toda la lógica de carga / procesamiento / cambio de tamaño de la imagen al hilo de fondo
- La reutilización de UITableViewCell está habilitada
- una vez que UITableViewCell está a la vista borro los valores antiguos (configuración para anular) y comienzo el hilo de fondo para cargar la imagen
- en este punto estamos en el hilo de fondo y estoy agregando 500 ms de retraso para evitar que la nueva imagen se ajuste a menudo (en caso de que estemos desplazándonos rápidamente) (vea la explicación a continuación)
- si el UIImage existe en el caché de imágenes estáticas (diccionario común con instancias de UIImage), busque ese y vaya al paso 9.
- de lo contrario, cargue una nueva imagen del paquete (imageWithName) usando el url al paquete de la aplicación (en el mundo real, las imágenes del escenario se almacenarán en el almacenamiento de la aplicación, no en un paquete)
- una vez que se carga la imagen, redimensionela a 120x120 utilizando el contexto gráfico
- guardar el tamaño de la imagen en la memoria caché de imágenes estáticas
- en este punto tenemos instancia para UIImage y el proceso está en el hilo de fondo. A partir de aquí volvemos a UI Thread con la imagen dada
- si se borró el contexto de datos (por ejemplo, UITableViewCell desapareció o se reutilizó para mostrar otra imagen) omitimos el procesamiento de la imagen disponible actualmente.
- si el contexto de datos es el mismo: asigna UIImage a UIImageView con una animación alfa (UIView.Animate)
- una vez que UITableViewCell está fuera de la vista, borre el contexto de datos
Originalmente, antes de iniciar el nuevo hilo de fondo para recuperar la imagen aquí (paso 1), estaba la verificación de caché de UIImage sin hilo de fondo. En este caso, si tenemos la imagen en la caché, la asignamos de manera instantánea y esto presenta un gran retraso durante el desplazamiento rápido (asignamos imágenes a menudo siempre que las obtengamos al instante). Esas líneas se comentan en mi ejemplo adjunto a continuación.
Todavía hay dos problemas:
- En algún momento durante el desplazamiento, todavía tengo un pequeño retraso (en el momento en que asigné un nuevo UIImage a UIImageView.
- (este es más notable) cuando toca el elemento y vuelve de los detalles hay un retraso justo antes de que finalice la animación de navegación hacia atrás.
Cualquier sugerencia de cómo lidiar con esos dos problemas o cómo optimizar mi escenario se aprecia
Tenga en cuenta esa muestra escrita en Xamarin, pero no creo que Xamarin sea la causa del problema, siempre que tenga el mismo problema para la aplicación escrita en ObjectiveC también.
Sub-clasifico CoreDataTableViewController de Paul Hegarty y empleo miniaturas de mis fotos en CoreDataTableView.
Busque los ejemplos en la Lección 14 titulada FlickrFetcher y Photomania . También deberá descargar CoreDataTableViewController en ese mismo enlace.
Cree una entidad CoreData con un título apropiado y defina los atributos (variables de datos) que desee. Tendrá que definir dos atributos "Transformables", uno para la foto y otro para la miniatura.
A continuación, cargue la miniatura en CoreDataTableView:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{NSArray * exceptions = [NSArray arrayWithObjects: @ "SCR", @ "DNS", @ "NT", @ "ND", @ "NH", nada];
static NSString *CellIdentifier = @"resultsDisplayCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
MarksFromMeets *athleteMarks = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString* date = [ITrackHelperMethods dateToAbbreviatedString:athleteMarks.meetDate];
NSMutableString *title = [NSMutableString stringWithFormat:@"%@", athleteMarks.markInEvent];
NSMutableString *subTitle = [NSMutableString stringWithFormat:@"%@ - %@",date, athleteMarks.meetName];
[title replaceOccurrencesOfString:@"(null)"
withString:@""
options:0
range:NSMakeRange(0, [title length])];
// cell.imageView.image = athleteMarks.photoThumbNail; // Don''t like image in front of record.
[cell.textLabel setFont:[UIFont
fontWithName:@"Helvetica Neue" size:18]];
[cell.detailTextLabel setFont:[UIFont fontWithName:@"Helvetica Neue" size:16]];
[cell.detailTextLabel setTextColor:[UIColor grayColor]];
// make selected items orange
if ([athleteMarks.eventPR integerValue] != 0
&& (![exceptions containsObject:athleteMarks.markInEvent])) {
title = [NSMutableString stringWithFormat:@"%@ (PR)",title];
[cell.textLabel setTextColor:[UIColor redColor]];
}
else if ([athleteMarks.eventSB integerValue] != 0
&& (![exceptions containsObject:athleteMarks.markInEvent])) {
title = [NSMutableString stringWithFormat:@"%@ (SB)",title];
[cell.textLabel setTextColor:[UIColor orangeColor]];
} else {
[cell.textLabel setTextColor:[UIColor grayColor]];
}
cell.textLabel.text = title;
cell.detailTextLabel.text = subTitle;
cell.indentationLevel = indentationLevelOne;
cell.indentationWidth = indentationForCell;
return cell;
}
Si lo desea, puedo enviarle un ejemplo de una Categoría para la Subclase NSManagedObject de una Entidad. Esta categoría carga la foto y la miniatura en la entidad CoreData. La primera vez será lento. Sin embargo, después de eso, el usuario debería poder desplazarse por TableView sin problemas y luego todos los resultados actualizados se cargarán automáticamente. Házmelo saber.
Una cosa buena es que CoreData maneja toda la administración de la memoria.
¡Buena suerte!
Pruebe la biblioteca Async Display de Facebook.
https://github.com/facebook/AsyncDisplayKit
Realmente fácil de usar .. de su guía: http://asyncdisplaykit.org/guide/
_imageNode = [[ASImageNode alloc] init];
_imageNode.backgroundColor = [UIColor lightGrayColor];
_imageNode.image = [UIImage imageNamed:@"hello"];
_imageNode.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f);
[self.view addSubview:_imageNode.view];
Esto decodifica la imagen en un hilo de fondo.
No estoy seguro de si es fácil usar las bibliotecas de iOS en Xamarin, pero si es fácil, pruebe esto.
Tal vez podrías probar SDWebImage
en SDWebImage
lugar. También es un componente de xamarin que crea un descargador de imágenes asíncronas y memoria asíncrona y el almacenamiento en caché de imágenes de disco con manejo automático de caducidad de caché. Usarlo probablemente significaría tirar un montón de código escrito, pero podría valer la pena, y su código será mucho más simple. En iOS también puede configurar un SDWebImageManager
dentro de viewDidLoad de un controlador:
- (void)viewDidLoad{
...
SDWebImageManager *manager = [SDWebImageManager sharedManager];
manager.delegate = self;
...
}
y configura el controlador de vista como el delegado. Luego, cuando se llama al siguiente método delegado:
- (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL
puede escalar sus imágenes a los pulgares del tamaño apropiado antes de almacenarlos en caché.
Espero que ayude.
¿Alguna vez trataste de poblar tu TableView
con solo una imagen de 120x120 que está guardada en tu Bundle
? De esta forma puede verificar, si ocurre el problema de su Image rendering
En lugar de cambiar el tamaño de todas sus imágenes a 120x120 y guardarlas en caché, recomendaría crear y usar una miniatura de todas sus imágenes. De alguna manera ya estás haciendo esto, pero lo estás haciendo un par de veces (cada vez que estás desplazándote o si tu caché está lleno).
En nuestro último proyecto, tuvimos un UICollectionView
con portadas de libros. La mayoría de las portadas tenían entre 400-800kb de tamaño y la sensación al desplazarse era realmente mala. Así que creamos una miniatura para cada imagen (miniaturas de alrededor de 40-50 kb) y utilizamos las miniaturas en lugar de portadas reales. ¡Funciona de maravilla! Adjunté la función de creación de miniaturas
- (BOOL) createThumbnailForImageAtFilePath:(NSString *)sourcePath withName:(NSString *)name {
UIImage* sourceImage = [UIImage imageWithContentsOfFile:sourcePath];
if (!sourceImage) {
//...
return NO;
}
CGSize thumbnailSize = CGSizeMake(128,198);
float imgAspectRatio = sourceImage.size.height / sourceImage.size.width;
float thumbnailAspectRatio = thumbnailSize.height/thumbnailSize.width;
CGSize scaledSize = thumbnailSize;
if(imgAspectRatio >= thumbnailAspectRatio){
//image is higher than thumbnail
scaledSize.width = scaledSize.height * thumbnailSize.width / thumbnailSize.height;
}
else{
//image is broader than thumbnail
scaledSize.height = scaledSize.width * imgAspectRatio;
}
UIGraphicsBeginImageContextWithOptions( scaledSize, NO, 0.0 );
CGRect scaledImageRect = CGRectMake( 0.0, 0.0, scaledSize.width, scaledSize.height );
[sourceImage drawInRect:scaledImageRect];
UIImage* destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSString* thumbnailFilePath = [[self SOMEDIRECTORY] stringByAppendingPathComponent:name];
BOOL success = [UIImageJPEGRepresentation(destImage, 0.9) writeToFile:thumbnailFilePath atomically:NO];
return success;
}
Weel tuve un problema similar, mi pergamino no fue suave. Estoy insertando en la tabla una UIImageView variable con dentro de labelViews. Lo que hice fue cambiar el método HeightforRowAtIndexPath para estimateHeightforRowAtIndexPath y ahora scroll es fluido.