miércoles, 24 de julio de 2013

Descarga asíncrona de imágenes desde una URL

Una de las reglas que debes seguir a rajatabla en la descarga de datos es la siguiente:
"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];
            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.

miércoles, 3 de julio de 2013

Añadir una fuente externa

Más tarde o más temprano, nos encontraremos con que un diseñador (un cliente no suele entrar a ese nivel detalle) nos pedirá un tipo de fuente poco habitual. Si todavía no somos muy experimentados se nos puede ocurrir la feliz idea de añadir la fuente como otra cualquiera,

UIFont *font = [UIFont fontWithName:@"Fortheloveofhate" size:17.];

Si además, no es una fuente muy extravagante y estamos un poco verdes en todo el tema relacionado con diseño no sabremos si se ha tomado correctamente, ya que iOS nos muestra una fuente por defecto.

Por lo tanto para añadir una fuente externa debemos seguir los siguientes pasos:

1.   Añadimos el ttf a una carpeta de recursos. En el .plist del proyecto añadimos una fila con el key Fonts provided by application de tipo NSArray. A éste, le añadiremos un item de tipo string y value el nombre de la fuente, en este caso Fortheloveofhate.ttf.





2. Ahora simplemente tenemos que crear la fuente y añadirla donde queramos:

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.,0.,150.,50.)];
    [label setBackgroundColor:[UIColor clearColor]];
    [label setText:@"Oh My Apps!"];
    
    UIFont *font = [UIFont fontWithName:@"Fortheloveofhate" size:17.];
    [label setFont:font];
    [label setCenter:self.view.center];


NOTA: Si queremos conocer todas las fuentes que podemos utilizar en nuestro dispositivo podemos añadir el siguiente código:

    NSArray *fonts = [UIFont familyNames];
    for(UIFont *font in fonts)
    {
        NSLog(@"%@",font);
    }