"Las descargas de datos siempre serán ASÍNCRONAS"Si yo fuese responsable de la contratación de algún desarrollador no haría las estúpidas preguntas a las que estamos acostumbrados como ¿ Cuánto te gustaría ganar? o ¿ Cómo te ves dentro de 5 años? . Sin embargo, cogería un Mac, abriría el XCode y pediría que me hiciese una descarga de datos a través de alguna petición http. Si el candidato escribiese el siguiente código y me dijese que ya está hecho, la entrevista terminaría en ese preciso instante.
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.ohmyapps.es/images/xxxxxx.xxx"]];
Como no quiero escribir artículos largos dejaré para otro día el artículo acerca de NSURLConnection para descargas asíncronas y me centraré en un código que aparece a menudo en diferentes búsquedas por la red y puede resultar algo complicado ya que utiliza la tecnología de GCD (Grand Central Dispatch) para dispositivos multinúcleos y bloques. Este código sólo es válido para aplicaciones superiores a iOS 4.x (aunque ya no creo que nadie desarrolle para esas versiones). Deberemos seguir los siguientes pasos:
1. Copiamos el siguiente código en el archivo de cabecera:
void UIImageFromURL(NSURL * URL, void (^imageBlock)(UIImage * image), void (^errorBlock)(void));
2. Copiamos el siguiente código en el archivo de implementación:
void UIImageFromURL(NSURL * URL, void (^imageBlock)(UIImage * image), void (^errorBlock)(void) )
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^(void)
{
NSData * data = [[NSData alloc] initWithContentsOfURL:URL];
UIImage * image = [[UIImage alloc] initWithData:data];
{
imageBlock( image );
}
else
{
errorBlock();
}
});
});
}
Algún observador dirá ,"Pero si utilizas el mismo código que dices que no se debe utilizar nunca", a lo cual yo contestaré, sí pero con la salvedad de el método dispatch_async(dispatch_queue_t queue, ^(void)block);. Y qué hace este método os preguntaréis. Pues simplemente le pasa un bloque de código para su ejecución asíncrona en una cola.
3. Finalmente utilizamos el método donde lo necesitemos
NSLog(@"error!");
}
Para las próximas entradas veremos otra manera de descarga de datos asíncrona y el uso de alguna librería interesante.
1. Copiamos el siguiente código en el archivo de cabecera:
void UIImageFromURL(NSURL * URL, void (^imageBlock)(UIImage * image), void (^errorBlock)(void));
2. Copiamos el siguiente código en el archivo de implementación:
void UIImageFromURL(NSURL * URL, void (^imageBlock)(UIImage * image), void (^errorBlock)(void) )
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^(void)
{
NSData * data = [[NSData alloc] initWithContentsOfURL:URL];
UIImage * image = [[UIImage alloc] initWithData:data];
dispatch_async( dispatch_get_main_queue(), ^(void){
if( image != nil ){
imageBlock( image );
}
else
{
errorBlock();
}
});
});
}
Algún observador dirá ,"Pero si utilizas el mismo código que dices que no se debe utilizar nunca", a lo cual yo contestaré, sí pero con la salvedad de el método dispatch_async(dispatch_queue_t queue, ^(void)block);. Y qué hace este método os preguntaréis. Pues simplemente le pasa un bloque de código para su ejecución asíncrona en una cola.
3. Finalmente utilizamos el método donde lo necesitemos
UIImageFromURL( [NSURL URLWithString:@"http://www.ohmyapps.es/images/xxxxxx.xxx"], ^( UIImage * image )
{
//Aquí ejecutamos lo que queramos con nuestra imagen
}, ^(void){NSLog(@"error!");
//Bloque para ejecutar en caso de error
});}
Para las próximas entradas veremos otra manera de descarga de datos asíncrona y el uso de alguna librería interesante.
Buenos días Manuel, he llegado al blog a partir de LinkedIn, y ya me ha picado la curiosidad.
ResponderEliminarDe las mejores explicaciones que he visto sobre este tema "hoygan"!!
Simplemente bravo jeje. Un saludo!!
Pues muchas gracias. Espero sacar tiempo y seguir publicando artículos.
EliminarUn saludo.