2010-12-01 4 views
0

J'ai une classe timer, avec un nstimer à l'intérieur, qui envoie une notification à un uitableviewcontroller, et l'objet de notification (valeur du timer) est affecté dans une uitableviewcell. Mon problème est quand je touche l'écran pour faire défiler, l'arrêt de la minuterie, NSTimer ne démarre pas dans un autre thread? Comment je peux résoudre ce problème.nstimer stop lorsque vous touchez l'écran

Mon timerClass

#import "timerEtape.h" 
#import "FonctionUtile.h" 
#import "Mission.h" 

static timerEtape *sngTimerEtape = nil; 

@implementation timerEtape 

@synthesize repeatingTimerEtape; 
@synthesize dateComp; 
@synthesize questionCircuit; 
@synthesize b_Pause; 

+(timerEtape *) singletonTimer 
{ 
    @synchronized(self){ 
     if (sngTimerEtape == nil) 
     { 
      sngTimerEtape = [[timerEtape alloc]init]; 
     } 
    } 

    return sngTimerEtape; 
} 

-(id)init 
{ 
    self = [super init]; 

    if (self != nil) { 
     dateComp = [[NSDateComponents alloc] init]; 
     b_Pause = FALSE; 
    } 

    return self; 
} 

- (void)startTimer { 

    [repeatingTimerEtape invalidate]; 

    NSString * temps; 

    if (questionCircuit) { 

     temps = [[Mission singletonMission].circuitTerrain valeurChampEtapeCircuitEnCours:@"et_temps_etape" :FALSE]; 
    } 
    else { 
     temps = [[Mission singletonMission].histoireTerrain valeurChampQuestion:@"hi_temps_etape" :FALSE]; 
    } 

    if (!b_Pause) { 
     [dateComp setHour:0]; 
     [dateComp setMinute:[[FonctionUtile gauche:temps :2] intValue]]; 
     [dateComp setSecond:[[FonctionUtile droite:temps :2] intValue]]; 
    } 
    else { 
     b_Pause = FALSE; 
    } 

    self.repeatingTimerEtape = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateLabelTimerEtape:) userInfo:nil repeats:YES]; 
} 

-(void)pause 
{ 
    self.b_Pause = TRUE; 
    [repeatingTimerEtape invalidate]; 
} 

-(void)updateLabelTimerEtape:(NSTimer*)theTimer 
{ 

    if ([dateComp second] == 0) { 

     if ([dateComp minute] == 0) { 
      if ([dateComp hour] != 0) { 
       [dateComp setHour:[dateComp hour] -1]; 
       [dateComp setMinute:59]; 
       [dateComp setSecond:59]; 
      } 
      else { 
       [repeatingTimerEtape invalidate]; 
       [delegate performSelector:touchAction]; 
      } 

     } 
     else { 
      [dateComp setMinute:[dateComp minute] -1]; 
      [dateComp setSecond:59]; 
     } 
    } 
    else { 
     [dateComp setSecond:[dateComp second] -1]; 
    } 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"rafraichirTimerEtape" object:[NSString stringWithFormat:@"%02d:%02d", [dateComp minute],[dateComp second]]]; 
} 

-(void)setTarget:(id)target andAction:(SEL)action { 
    delegate = target; 
    touchAction = action; 
} 

-(void)dealloc 
{ 
    [dateComp release]; 
    [repeatingTimerEtape release]; 

    [super dealloc]; 
} 
@end 

et quand je reçois la notification dans ma classe UITableViewController

-(void)rafraichirTimerEtape:(NSNotification*)notification 
{ 
    [tempsRestant release]; 
    tempsRestant = [[notification object]copy]; 

    [table cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]].detailTextLabel.text = [notification object]; 
} 

thanx

Répondre

3

J'ai rencontré ce problème auparavant. En fait, NSTimer ne s'exécute pas dans un autre thread, il s'exécute toujours dans le thread sur lequel il est démarré. Il y a un concept de runloop dans iphone sdk, vous devriez le lire de here pour comprendre les minuteries. Dans ce concept, vous placez des tâches dans runloop et runloop les implémente séquentiellement. Le thread principal est toujours une boucle d'exécution et les travaux ui y sont exécutés. Donc, si vous démarrez votre minuteur dans le thread principal, il sera affecté par le traitement de l'interface utilisateur. Vous devez démarrer un nouveau thread, le configurer comme une boucle d'exécution et y démarrer vos minuteurs.

Editer: Voici un exemple de code du lien que j'ai posté. threadMain est la première fonction que le thread démarre.


- (void) threadMain 
{ 
    NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop]; 

    // Create and schedule the timer. 
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self 
       selector:@selector(doFireTimer:) userInfo:nil repeats:YES]; 

    NSInteger loopCount = 10; 

    do 
    { 
     // Run the run loop 10 times to let the timer fire. 
     [myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 
     loopCount--; 
    } 
    while (loopCount); 
} 

si vous voulez runloop courir à l'infini, mais mettre fin à une condition, utilisez plutôt


BOOL shouldKeepRunning = YES;  // global 

NSRunLoop *theRL = [NSRunLoop currentRunLoop]; 

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self 
     selector:@selector(doFireTimer:) userInfo:nil repeats:YES]; 

while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode 
     beforeDate:[NSDate distantFuture]]); 
+0

réponse Nice. Puis-je demander un petit échantillon de code? –