2011-07-26 33 views
7

Actualmente estoy cargando datos provenientes de un servicio JSON en el método viewDidLoad en UITableViewController. El problema es que los datos tardan en recuperarse y analizarse, la vista tarda en crearse. ¿Dónde está el mejor lugar para cargar esta información? Supongo que hay un gancho en alguna parte para cargar datos después de que se crea la vista. Al hacer esto, podré usar algunos UIActivityIndicatorView en la vista final. Gracias¿Cuándo cargar datos en UITableViewController?

Respuesta

1

Creo que lo que intentas preguntar es el flujo de trabajo para mostrar datos de un servicio web en una UITableView.

Aquí es lo que recomiendo:

  • Su viewDidLoad hace un NSURLRequest para su archivo JSON. También agrega una vista de carga a la vista actual (uso un UIView con un negro bg (0.5 alfa), más una etiqueta y UIActivityIndicator). En este método también establece un BOOL ivar (que debe agregar en su encabezado ) llamado loaded a NO.

  • Concat la información NSURLRequest, ya que se trata de un objeto de datos mutable .

  • Cuando sus NSURLRequest acabados, lo enciende de datos en una cadena, y analizar el JSON en una matriz de algún tipo (o diccionario si falta). En el mismo método, elimina la vista de carga y cambia su booleana loaded a SÍ. A continuación, le dice al tableView para recargar es de datos: [self.tableView reloadData];

Aquí es donde la magia sucede ... en la tabla de métodos vista

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (loaded) return [myArrayOfJSONObjects count]; 
    return 0; // Will only return 0 if the data is not downloaded 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSUInteger row = [indexPath row]; 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Configure the cell... 
    if (loaded) { 
     cell.textLabel.text = [myArrayOfParsedJSONObjects objectAtIndex:row]; 
     //Anything else you want to set 
    } 
    else { 
     //Do nothing :) - you shouldn't reach this else anyway because your numberOfRows method should stop it 
    } 
} 
+0

No exactamente. Esto es lo que ya hago. Cargué datos en viewDidLoad y llené la tabla en cellForRowAtIndexPath. Funciona, pero lo que dije es que en este caso, si el servicio JSON tarda 10 segundos en responder, la vista aparece 10 segundos después de que el usuario lo haya seleccionado. En mi caso, la vista se carga desde otra vista de tabla cuando el usuario hizo clic en una fila. –

+0

Entonces, ¿estás preguntando si hay algún lugar donde puedas cargarlo antes? –

+0

Puedo cargarlo en cualquier lugar, por supuesto, pero lo que quiero hacer es: 1/mostrar la vista (tabla potencialmente vacía) 2/cargar automáticamente los datos del servicio remoto 2 '/ mostrar un mensaje de espera mientras carga –

0

Puede abrir nueva visión y mostrar UIActivityIndicator con el mensaje de usuario, lo que está cargando datos nuevos para él.

En cuanto a mí, esta es la mejor opción, porque la interfaz sigue siendo responsable y el usuario ve lo que realmente hace algo y la aplicación no se cuelga.

+0

abro un nuevo ver con mensaje en cuyo caso dejo este cargador [tableview reloadData] –

5

Finalmente aquí es una solución basada en los comentarios: Lanzamiento de un hilo en viewDidLoad para obtener datos sin bloquear todo:

- (void) viewDidLoad 
{ 
    dataLoaded = NO; 

    [self initSpinner]; 
    [self launchLoadData]; 
... 
} 

-(void)launchLoadData { 
    NSLog(@"Launching thread"); 
    [NSThread detachNewThreadSelector:@selector(loadData) toTarget:self withObject:nil]; 
} 

- (void) loadData { 
    dataLoaded = NO; 
    NSLog(@" thread launched"); 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    [self loadDataFromURL:nil]; 
    dataLoaded = YES; 
    [self.tableView reloadData]; 
    [pool release]; 
} 

- (void)loadDataFromURL:(NSString*)url { 
    // start the spinner to show that loading may be time consuming... 
    [NSThread detachNewThreadSelector: @selector(spinBegin) toTarget:self withObject:nil]; 
    JSONLoader *loader = [[JSONLoader alloc] init]; 
    self.accounts = [loader getAccountsFromURL:@"http://foo/bar/repository.json"]; 
    [loader release]; 
    //[NSThread sleepForTimeInterval:3]; 
    [NSThread detachNewThreadSelector: @selector(spinEnd) toTarget:self withObject:nil]; 
} 

y el uso de la bandera para mostrar o no los datos en la tabla. tableView reloadData hará el resto cuando se llame desde el hilo.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (dataLoaded) return [self.accounts count]; 
    return 0; 
} 
Cuestiones relacionadas