Comment utiliser un NSTimer
? Quelqu'un peut-il me donner des instructions étape par étape?
Tout d’abord, j’aimerais attirer votre attention sur la documentation de Cocoa/CF (qui est toujours un excellent premier port d’escale). Les documents Apple comportent une section en haut de chaque article de référence intitulée "Guides d'accompagnement", qui répertorie les guides relatifs au sujet en cours de documentation (le cas échéant). Par exemple, avec NSTimer
, la documentation répertorie deux guides compagnons:
Selon votre situation, l'article sur les sujets de programmation par minuterie sera probablement le plus utile, alors que les sujets de thread sont liés mais pas les plus directement liés à la classe documentée. Si vous jetez un oeil à l'article Timer Programming Topics, il se divise en deux parties:
Pour les articles qui prennent ce format, il y a souvent un aperçu de la classe et de son utilité, puis quelques exemples de code sur comment comment l'utiliser, dans ce cas dans le " Utilisation des timers ". Il y a des sections sur "Créer et programmer une minuterie", "Arrêter une minuterie" et "Gestion de la mémoire". À partir de l'article, la création d'un minuteur programmé et non répétitif peut être réalisée de la manière suivante:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
Cela créera une minuterie déclenchée après 2,0 secondes et appelant targetMethod:
sur self
avec un argument, qui est un pointeur sur l'instance NSTimer
.
Si vous souhaitez ensuite examiner plus en détail la méthode, vous pouvez vous reporter à la documentation pour plus d'informations, mais le code contient également des explications.
Si vous souhaitez arrêter un minuteur qui se répète (ou arrêter un minuteur non répétitif avant son déclenchement), vous devez conserver un pointeur sur l'instance NSTimer
qui a été créée. souvent, il faudra que ce soit une variable d'instance pour pouvoir y faire référence dans une autre méthode. Vous pouvez ensuite appeler invalidate
sur l'instance NSTimer
:
[myTimer invalidate];
myTimer = nil;
Il est également judicieux de nil
sur la variable d'instance (par exemple, si votre méthode qui invalide le minuteur est appelée plusieurs fois et que la variable d'instance n'a pas été définie sur nil
et que NSTimer
instance a été désallouée, une exception sera lancée).
Notez également le point sur la gestion de la mémoire au bas de l'article:
Étant donné que la boucle d’exécution maintient la minuterie, du point de vue de la gestion de la mémoire , il n’est généralement pas nécessaire de conserver une référence à une minuterie après l’avoir planifiée . Étant donné que le minuteur est passé en tant qu'argument lorsque vous spécifiez sa méthode en tant que sélecteur, , vous pouvez invalider un minuteur répété, le cas échéant, au sein de cette méthode . Toutefois, dans de nombreux cas, vous souhaitez également pouvoir invalider le chronomètre, même avant son démarrage. Dans ce cas, vous devez conserver une référence au temporisateur afin de pouvoir lui envoyer un message d'invalidation à tout moment . Si vous créez un minuteur non planifié (voir "Minuteurs non planifiés"), vous devez alors conserver une référence forte au minuteur (dans un environnement compté de références, vous la conservez) afin qu'il ne soit pas désalloué avant de l'utiliser.
il y a plusieurs façons d'utiliser une minuterie:
1) programmé & utiliser sélecteur
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(onTick:)
userInfo: nil repeats:NO];
En remarque, au lieu d'utiliser un minuteur qui ne se répète pas et appelle le sélecteur après un intervalle spécifié, vous pouvez utiliser une instruction simple comme celle-ci:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
cela aura le même effet que l'exemple de code ci-dessus; mais si vous voulez appeler le sélecteur tous les n fois, vous utilisez le temporisateur avec les répétitions suivantes: YES;
2) minuterie auto-programmée
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) minuterie non planifiée et utilisation de l'invocation
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];
et après cela, vous démarrez le chronomètre manuellement chaque fois que vous avez besoin de ceci:
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];
Et comme note, onTick: method ressemble à ceci:
-(void)onTick:(NSTimer *)timer {
//do smth
}
Quelque chose comme ça:
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}
#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
Les réponses manquent à un chronomètre spécifique de l'heure du jour:
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];
Bien sûr, remplacez "doRefresh" par la méthode souhaitée par votre classe
essayez de créer l’objet calendrier une fois et de rendre l’allUnits statique pour plus d’efficacité.
l'ajout d'un composant à heure fonctionne parfaitement, aucun test de minuit n'est nécessaire ( link )