NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
hasta aqui todo bien, el problema es cuando quiero poner un preloading (SVProgressHUD)
resulta que si muestro el loader [SVProgressHUD show] y cargo el json en viewDidLoad se muestra el preloading se carga justo al cargar la tabla no al hacer la llamada al servidor.
-------
he probado de mostar el preloading en el evento viewDidLoad y cargar el json en el evento viewDidAppear, pero funciona parcialmente. se muestra el preloading, se carga el json, pero luego la tabla no se actualiza [tableView reloadData];
-------
si ayuda aclarar como detalle al cargar el json relleno un NSMutableArray *arrayC;
se os ocurre alguna solución?
//Iniciar el progressHUD
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSData *data= .....
dispatch_async(dispatch_get_main_queue(), ^{
//parar el SVProgressHUD
});
});
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return[arrayC count];
}
he probado de mover [tableView reloadData]; dentro de dispatch_async(dispatch_get_global_queue(0, 0), ^{ y en dispatch_async(dispatch_get_main_queue(), ^{ pero igual :/
alguna idea?
- (void)loadDataWithSuccessCallback:(void (^)(NSDictionary *data))callback
El motivo de usar blocks es porque va a ser una tarea asíncrona: la llamada a ese método no va a acabar cuando acabe la carga de los datos, sino que acabará "inmediatamente". Esto es así porque se va a llamar a ese método desde el "main thread' (por ejemplo, en - (void)viewDidLoad), y si se tarda en devolver de ese método tanto como tarda el request, durante todo ese tiempo la interfaz no responderá, y la aplicación parecerá estar bloqueada. Te recomiendo que leas este documento de Apple para entender todo lo relativo a los blocks y GCD (que es el API en C que nos permite hacer cosas como coger un "block" y decir que queremos que se ejecute asíncronamente en otro hilo): http://developer.apple.com/library/mac/#featuredarticles/BlocksGCD/_index.html
Este método puede usar por ejemplo AFNetworking: https://github.com/AFNetworking/AFNetworking que es un framework para trabajar con todo lo relativo a requests a un servidor. Pero si lo que quieres en este caso es simplemente traerte el contenido de un archivo, puedes hacerlo en ese método directamente. Ejemplo:
- (void)loadDataWithSuccessCallback:(void (^)(NSArray *data))callback
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Lo que hagamos aquí dentro ocurre asíncronamente.
NSURL *url = [NSURL URLWithString:@"http://abcd.com/somefile.json"];
NSData *data = [NSData dataWithContentsOfURL:url]; // Ésta es la llamada que bloquea. Esto tarda tanto en ejecutarse como tarde el teléfono en traerse ese archivo de internet.
// Extraemos el diccionario del JSON usando el API de iOS5
NSArray *dataArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
dispatch_async(dispatch_get_main_queue(), ^{
// Ahora pedimos que este otro block se ejecute en el "hilo principal" / main queue (en el de la UI, desde donde nos llamaron al método).
// Llamamos al callback con los datos. Esta forma de trabajar estoy convencido de que te resulta muy familiar a pasar objetos function() en javascript ;)
callback(dataArray);
});
}); // Esta llamada a función devuelve inmediatamente el control
}
Y la llamada podría ser algo así:
- (void)viewDidLoad
{
// Le pedimos a nuestro objeto que descargue los datos
[self.dataDownloader loadDataWithSuccessCallback:^(NSArray *data) {
// Cuando ha acabado, asignamos los datos a un property
self.data = data;
// Y le pedimos a la tabla que se actualice. En el método cellForRowAtIndexPath: usamos [self.data objectAtIndex:indexPath.row] y listo :)
[self.tableView reloadData];
}];