Respuestas:
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 llamada "Guías complementarias", que enumera las guías para el tema que se está documentando (si existe). Por ejemplo, con NSTimer
, la documentación enumera dos guías complementarias:
Para su situación, es probable que el artículo Temas de programación del 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 está documentando. Si echa un vistazo al artículo de Temas de programación del temporizador, se divide en dos partes:
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 muestra sobre cómo usarlo, en este caso en la sección "Uso de temporizadores". Hay secciones sobre "Crear y programar un temporizador", "Detener un temporizador" y "Administración de memoria". A partir del artículo, la creación de un temporizador no repetido programado 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 dispara después de 2,0 segundos y llama targetMethod:
sobre self
con un argumento, que es un puntero a la NSTimer
instancia.
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 sobre el código.
Si desea detener un temporizador que es uno que se repite (o detener un temporizador que no se repite antes de que se active), debe mantener un puntero a la NSTimer
instancia que se creó; a menudo esto tendrá que ser una variable de instancia para que pueda consultarlo en otro método. Luego puede llamar invalidate
a la NSTimer
instancia:
[myTimer invalidate];
myTimer = nil;
También es una buena práctica nil
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 nil
y la NSTimer
instancia se ha desasignado, arrojará una excepción).
Tenga en cuenta también el punto sobre la gestión de memoria al final del artículo:
Debido a que el ciclo de ejecución mantiene el temporizador, desde la perspectiva de la administración de memoria , generalmente no es necesario mantener una referencia a un temporizador después de haberlo programado . Dado que el temporizador se pasa como argumento cuando especifica su método como 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, para poder enviarle un mensaje de invalidación cuando sea apropiado. Si crea un temporizador no programado (consulte “Temporizadores no programados”), debe mantener una fuerte referencia al temporizador (en un entorno de recuento de referencia, lo conserva) para que no se desasigne antes de usarlo.
YES
por repeats:
cuando llames scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
. Si lo hace, asegúrese de mantener una referencia a la NSTimer
instancia (es devuelta por el método) y siga el punto de Administración de memoria como se detalla anteriormente.
target
y selector
. Por ejemplo, si su objetivo es self
y el selector es timerMethod:
, el método llamado cuando se dispara el temporizador se timerMethod:
define en el self
. Luego puede poner el código que desee en ese método, y se llamará al método cada vez que se active el temporizador. Tenga en cuenta que el método llamado cuando se activa el temporizador (que pasa como selector:
) solo puede tomar un argumento (que cuando se llama es un puntero a la NSTimer
instancia).
self
"
Hay un par de formas de usar un temporizador:
1) temporizador programado y selector de uso
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(onTick:)
userInfo: nil repeats:NO];
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 muestra anterior; pero si desea llamar al selector cada enésima vez, use el temporizador con repeticiones: YES;
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];
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, inicias el temporizador manualmente cuando lo necesites así:
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];
Y como nota, onTick: el método se ve así:
-(void)onTick:(NSTimer *)timer {
//do smth
}
Algo como esto:
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
#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
MyViewController
nunca se desasigna.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}
A las respuestas les falta un temporizador específico de la hora del día aquí, 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 que allUnits sea estático para mayor eficiencia.
agregar un componente de una hora funciona bien, no es necesario realizar una prueba de medianoche ( enlace )