Retrasar la ejecución de un método en Cocoa
En Cocoa tenemos la posibilidad de enviar un mensaje a un objeto pasados n segundos con performSelector:withObject:afterDelay: y demás métodos similares definidos en NSObject.
Sin embargo, a veces se echa de menos el poder ejecutar código arbitrario (no necesariamente un método o solo un método) con un cierto retraso. Para esto hay dos soluciones, ambas basadas en Bloques.
Primera solución: dispatch_after()
La función dispatch_after(), proporcionada por Grand Central Dispatch (GCD) acepta un cierto número de nanosegundos (tal como devuelve dispatch_time()), la cola en la que se va a ejecutar y un bloque de tipo void ^void.
Es decir, no acepta parámetros ni devuelve nada. La falta de parámetros del bloque no es una limitación, ya que como recordaremos, los bloques capturan el entorno léxico donde se ejecutan.
Un ejemplo de su uso podría ser:
|
1 2 3 4 5 6 |
int64_t delta = 1.0e9 * 4; // 4 segundos expresados en nanosegundos
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, delta);
dispatch_after(delay, dispatch_get_main_queue(), ^(void){
NSLog(@"Ya han pasado los 4 segundos!");
}); |
Sin embargo, esta solución tiene varias pegas:
- No es orientada a objeto, ya que Grand Central Dispatch es una API de C.
- Nos obliga a escribir mucho código y carece de la sencillez y elegancia de performSelector:withObject:afterDelay:
Segunda solución: Una categoría sobre NSObject
Vamos a crear una categoría sobre NSObject, que le añade un método similar a performSelector:withObject:afterDelay: llamado performBlock:afterDelay:
Interfase
Cursos iOS de CocoaMental
Aprovecha el mundo de oportunidades que la programación y desarrollo para iPhone & iPad brinda en estos momento. Fórmate o a tu equipo con nuestros cursos “gourmet” de iOS para programadores y NO programadores.
Somos especialistas en Apple, nos preparamos con los mejores del mundo y eso, hace la diferencia.
Todo esto probado y comprobado repetidamente por todos nuestros alumnos y clientes corporativos:
- Máximo nivel técnico,
- Grupos súper reducidos,
- Metodología de enseñanza única, 100% pragmática y enfocada a resultados,
- Acceso directo a los formadores,
- Atención continuada antes, durante y después del curso.
@frr149 pues yo todavía no estoy en un proyecto IOS pero estoy aprovechando el poco tiempo libre haciendo una aplicación.— @SergioBEscudero de la Formación para Unisys., Twitter
Fernando posee un conocimiento inmenso sobre IOS4 lo que le permite impartir una formación de calidad que se adapta a las necesidades del cliente. Su método de enseñanza es muy cercano y práctico, permitiendo asimilar los conceptos más complicados a través de la aplicación de esos conceptos a casos prácticos. En resumen, ha sido un placer trabajar con el y los resultados han sido inmejorables.— Consultor en Unisys, Linkedin
La formación es excelente para iniciarse en el desarrollo de apps para iOS— Alumno iOS Básico Barcelona
|
1 2 3 4 5 6 7 8 |
#import
@interface NSObject (NSObject_FRRObject)
-(void)performBlock:(void (^)(void))block
afterDelay: (NSTimeInterval) delayInSeconds;
@end |
Implementación
|
1 2 3 4 5 6 7 8 9 |
#import "NSObject+FRRObject.h"
@implementation NSObject (NSObject_FRRObject)
-(void)performBlock:(void (^)(void))block
afterDelay: (NSTimeInterval) delayInSeconds{ dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,
delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), block);
}@end |
Uso
|
1 2 3 |
[self performBlock:^{
NSLog(@"En dos palabras y 3 segundos, ObjectiveC es IM PRESIONANTE");}
afterDelay:3]; |
Conclusión
Al utilizar una categoría sobre NSObject podemos unir la flexibilidad de los bloques, con la sencillez y elegancia de performSelector:withObject:afterDelay: encapsulando así la API C de Grand Central Dispatch (GCD).
Fernando Rodríguez
Sígueme en twitter.
Cursos de desarrollo iPhone






4 Responses to Cómo retrasar la ejecución de un bloque en Objective C