objective c - serrano - ¿Cómo uso NSTimer?
el jamon serrano caduca (6)
¿Cómo uso un NSTimer
? ¿Alguien puede darme instrucciones paso a paso?
Algo como esto:
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
En primer lugar, me gustaría llamar su atención sobre la documentación de Cocoa / CF (que siempre es un excelente primer puerto de escala). Los documentos de Apple tienen una sección en la parte superior de cada artículo de referencia denominado "Guías complementarias", que enumera las guías para el tema que se documenta (si existe). Por ejemplo, con NSTimer
, la documentación enumera dos guías complementarias:
Para su situación, es probable que el artículo de Temas de programación con temporizador sea el más útil, mientras que los temas de subprocesos están relacionados pero no los más directamente relacionados con la clase que se documenta. Si echa un vistazo al artículo de Temas de Programación del Temporizador, se divide en dos partes:
- Temporizadores
- Usando los temporizadores
Para los artículos que toman este formato, a menudo hay una descripción general de la clase y para qué se usa, y luego un código de ejemplo sobre cómo usarlo, en este caso, en la sección "Uso de temporizadores". Hay secciones sobre "Creación y programación de un temporizador", "Detención de un temporizador" y "Administración de memoria". A partir del artículo, la creación de un temporizador programado y no repetitivo se puede hacer de la siguiente manera:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
Esto creará un temporizador que se targetMethod:
después de 2,0 segundos y llama a targetMethod:
on self
con un argumento, que es un puntero a la instancia de NSTimer
.
Si luego desea ver con más detalle el método, puede consultar los documentos para obtener más información, pero también hay una explicación en torno al código.
Si desea detener un temporizador que se repite (o detener un temporizador que no se repite antes de que se active), debe mantener un puntero a la instancia de NSTimer
que se creó; a menudo, será necesario que sea una variable de instancia para que pueda consultarla en otro método. Luego puede llamar a invalidate
en la instancia de NSTimer
:
[myTimer invalidate];
myTimer = nil;
También es una buena práctica eliminar la variable de instancia (por ejemplo, si su método que invalida el temporizador se llama más de una vez y la variable de instancia no se ha establecido en nil
y la instancia de NSTimer
se ha desasignado, se producirá una excepción) .
Tenga en cuenta también el punto sobre la gestión de memoria en la parte inferior del artículo:
Debido a que el bucle de ejecución mantiene el temporizador, desde la perspectiva de la administración de la memoria normalmente no hay necesidad de mantener una referencia a un temporizador después de haberlo programado . Como el temporizador se pasa como un argumento cuando especifica su método como un selector, puede invalidar un temporizador de repetición cuando sea apropiado dentro de ese método . Sin embargo, en muchas situaciones, también desea la opción de invalidar el temporizador, tal vez incluso antes de que comience. En este caso, debe mantener una referencia al temporizador, de modo que pueda enviar un mensaje de invalidación cuando sea apropiado . Si crea un temporizador no programado (consulte "Temporizadores no programados"), entonces debe mantener una referencia sólida al temporizador (en un entorno de referencia, lo retiene) para que no se desasigne antes de usarlo.
Hay un par de maneras de usar un temporizador:
1) temporizador programado y con selector
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(onTick:)
userInfo: nil repeats:NO];
- si configura las repeticiones en NO, el temporizador esperará 2 segundos antes de ejecutar el selector y luego se detendrá;
- si se repite: SÍ, el temporizador se iniciará inmediatamente y repetirá llamando al selector cada 2 segundos;
- para detener el temporizador se llama el método de desvalidación del temporizador: [t invalidar];
Como nota al margen, en lugar de usar un temporizador que no se repite y llama al selector después de un intervalo específico, puede usar una declaración simple como esta:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
esto tendrá el mismo efecto que el código de ejemplo anterior; pero si desea llamar al selector cada vez n, use el temporizador con repeticiones: SÍ;
2) temporizador auto-programado
NSDate *d = [NSDate dateWithTimeIntervalSinceNow: 60.0];
NSTimer *t = [[NSTimer alloc] initWithFireDate: d
interval: 1
target: self
selector:@selector(onTick:)
userInfo:nil repeats:YES];
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer:t forMode: NSDefaultRunLoopMode];
[t release];
- esto creará un temporizador que se iniciará en una fecha personalizada especificada por usted (en este caso, después de un minuto), y se repetirá cada segundo.
3) temporizador no programado y uso de invocación
NSMethodSignature *sgn = [self methodSignatureForSelector:@selector(onTick:)];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sgn];
[inv setTarget: self];
[inv setSelector:@selector(onTick:)];
NSTimer *t = [NSTimer timerWithTimeInterval: 1.0
invocation:inv
repeats:YES];
y después de eso, inicia el temporizador manualmente cada vez que lo necesita así:
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];
Y como nota, el método onTick: se ve así:
-(void)onTick:(NSTimer *)timer {
//do smth
}
Las respuestas faltan una hora específica del temporizador del día aquí está en la próxima hora:
NSCalendarUnit allUnits = NSCalendarUnitYear | NSCalendarUnitMonth |
NSCalendarUnitDay | NSCalendarUnitHour |
NSCalendarUnitMinute | NSCalendarUnitSecond;
NSCalendar *calendar = [[ NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents = [calendar components: allUnits
fromDate: [ NSDate date ] ];
[ weekdayComponents setHour: weekdayComponents.hour + 1 ];
[ weekdayComponents setMinute: 0 ];
[ weekdayComponents setSecond: 0 ];
NSDate *nextTime = [ calendar dateFromComponents: weekdayComponents ];
refreshTimer = [[ NSTimer alloc ] initWithFireDate: nextTime
interval: 0.0
target: self
selector: @selector( doRefresh )
userInfo: nil repeats: NO ];
[[NSRunLoop currentRunLoop] addTimer: refreshTimer forMode: NSDefaultRunLoopMode];
Por supuesto, sustituya "doRefresh" con el método deseado de su clase
intente crear el objeto de calendario una vez y haga de allUnits una estática para mayor eficiencia.
agregar un componente de una hora funciona bien, sin necesidad de una prueba de medianoche ( link )
#import "MyViewController.h"
@interface MyViewController ()
@property (strong, nonatomic) NSTimer *timer;
@end
@implementation MyViewController
double timerInterval = 1.0f;
- (NSTimer *) timer {
if (!_timer) {
_timer = [NSTimer timerWithTimeInterval:timerInterval target:self selector:@selector(onTick:) userInfo:nil repeats:YES];
}
return _timer;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
-(void)onTick:(NSTimer*)timer
{
NSLog(@"Tick...");
}
@end
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}