tutorial example efecto create cellforrowat apple objective-c uitableview cocoa synchronous

objective-c - example - uitableview tutorial



Los datos no se cargan en UITableView hasta que me desplazo (7)

¡Estaba teniendo exactamente el mismo problema! Quería que UITableView se completara antes de que apareciera el controlador de vista. La publicación de Envil me dio la información que necesitaba, pero mi solución terminó siendo diferente.

Esto es lo que hice (remodelado para encajar en el contexto de la pregunta asker).

- (void)viewDidLoad { [super viewDidLoad]; [self performSelectorInBackground:@selector(fethchData) withObject:nil]; } - (void)viewWillAppear { [tableView reloadData]; }

Estoy tratando de cargar datos analizados en las celdas, pero el problema es que está sucediendo de forma síncrona y UitableView no se muestra hasta que los datos se hayan terminado de cargar. Intenté resolver el problema utilizando performSelectorInBackground, pero ahora los datos no se cargan en las celdas hasta que empiezo a desplazarme. Aquí está mi código:

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self performSelectorInBackground:@selector(fethchData) withObject:nil]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. self.listData = nil; self.plot=nil; } -(void) fethchData { NSError *error = nil; NSURL *url=[[NSURL alloc] initWithString:@"http://www.website.com/"]; NSString *strin=[[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil]; HTMLParser *parser = [[HTMLParser alloc] initWithString:strin error:&error]; if (error) { NSLog(@"Error: %@", error); return; } listData =[[NSMutableArray alloc] init]; plot=[[NSMutableArray alloc] init]; HTMLNode *bodyNode = [parser body]; NSArray *contentNodes = [bodyNode findChildTags:@"p"]; for (HTMLNode *inputNode in contentNodes) { [plot addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; } NSArray *divNodes = [bodyNode findChildTags:@"h2"]; for (HTMLNode *inputNode in divNodes) { [listData addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; //here you check for PreCreated cell. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } //Fill the cells... cell.textLabel.text = [listData objectAtIndex:indexPath.row]; cell.textLabel.font = [UIFont boldSystemFontOfSize:14]; cell.textLabel.numberOfLines=6; cell.textLabel.textColor=[UIColor colorWithHue:0.7 saturation:1 brightness:0.4 alpha:1]; cell.detailTextLabel.text=[plot objectAtIndex:indexPath.row]; cell.detailTextLabel.font=[UIFont systemFontOfSize:11]; cell.detailTextLabel.numberOfLines=6; return cell; }


Coloque esto en algún lugar después de que los datos se carguen correctamente :

dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; });

Esto soluciona el problema de llamar a una actualización de GUI mientras no está en el hilo principal.

Este código usa la tecnología GCD de Apple para obligar a la función de datos de recarga a ejecutarse en el hilo principal. Lea más acerca de la Guía de programación de concurrencia para obtener más información (es un campo bastante amplio, por lo que es difícil de explicar en el comentario). De todos modos, no es muy recomendable si no lo entiende bien porque hace que el programa falle en algunos casos excepcionales.


Primero, esto semi-resolvió mi problema relacionado. Quiero redondear las esquinas de una imagen en una celda de la tabla. El envío asincrónico solucionó el problema de algunas, pero no de todas las imágenes. ¿Algunas ideas?

En segundo lugar, creo que se supone que debes evitar crear un ciclo de referencia fuerte mediante el uso de una lista de captura de cierre como esta:

DispatchQueue.main.async(execute: { [weak weakSelf = self] () -> Void in weakSelf!.tableView.reloadData() })

Ver: https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID52


Todo lo que necesita hacer es cuando tenga una actualización de sus datos de back-end, llame

[tableView reloadData];

Como esto está sucediendo sincrónicamente, probablemente deberías tener una función como

-(void) updateTable { [tableView reloadData]; }

y después de agregar los datos en su llamada de descarga

[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:NO];


Tuve este problema y estaba lidiando con eso todo el día.

Estoy usando celdas estáticas y reloadData está causando la carga incorrecta, muestra solo las celdas visibles y elimina las otras. Lo que noté es que cuando me desplacé hacia abajo (y en valor negativo) las celdas se cargaron correctamente, así que escribí este código y funcionó, aunque no me gusta dejarlo así.

Dispara si encuentras una mejor solución.

-(void)reloadTableView{ CGPoint point = self.tableSettings.tableView.contentOffset; [self.tableSettings.tableView reloadData]; [UIView animateWithDuration:.001f animations:^{ [self.tableSettings.tableView setContentOffset:CGPointMake(point.x, -10)]; } completion:^(BOOL finished) { [UIView animateWithDuration:.001f animations:^{ [self.tableSettings.tableView setContentOffset:point]; } completion:^(BOOL finished) { }]; }]; }


U puede usar [cell setNeedsDisplay]; por ejemplo:

dispatch_async(dispatch_get_main_queue(), ^{ [cell setNeedsDisplay]; [cell.contentView addSubview:yourView]; });


Para swift 3:

DispatchQueue.main.async(execute: { () -> Void in self.tableView.reloadData() })

Para swift 2:

dispatch_async(dispatch_get_main_queue(), { () -> Void in self.tableView.reloadData() })