web-dev-qa-db-fra.com

Comment utiliser NSTimer?

Comment utiliser un NSTimer? Quelqu'un peut-il me donner des instructions étape par étape?

345
lab12

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:

  • Minuteries
  • Utiliser les timers

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.

617
Alex Rozanski

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];
  • si vous réglez les répétitions sur NO, le minuteur attendra 2 secondes avant de lancer le sélecteur, puis s'arrêtera.
  • si répéter: OUI, le chronomètre commencera immédiatement et répétera l'appel du sélecteur toutes les 2 secondes;
  • pour arrêter la minuterie, vous appelez la méthode -invalidate de la minuterie: [t invalidate];

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];
  • cela créera une minuterie qui se lancera elle-même à une date personnalisée spécifiée par vous (dans ce cas, après une minute), et se répétera toutes les secondes

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
}
332
Woofy

Quelque chose comme ça:

NSTimer *timer;

    timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
                     target: self
                     selector: @selector(handleTimer:)
                     userInfo: nil
                     repeats: YES];
59
ennuikiller
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];

-(void)timerCalled
{
     NSLog(@"Timer Called");
     // Your Code
}
5
Mohit
#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
5
Dan

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 )

2
gjpc