2010-09-11 9 views
9

Ho due NSTimers nella mia app per iPhone. DecreaseTimer funziona correttamente, ma TimerCountSeconds si arresta in modo anomalo quando chiamo [timerCountSeconds isValid] o [timerCountSeconds invalidate]. Sono usati così:NSTimer si arresta in modo anomalo, quando chiamo [Timer isValid] o [Timer invalidate]

-(id)initialize { //Gets called, when the app launches and when a UIButton is pressed 
if ([timerCountSeconds isValid]) { 
    [timerCountSeconds invalidate]; 
} 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //Gets called, when you begin touching the screen 
//.... 
if ([decreaseTimer isValid]) { 
    [decreaseTimer invalidate]; 
    } 
timerCountSeconds = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(runTimer) userInfo:nil repeats:YES]; 
//.... 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {//Gets called, when you stop touching the screen(not if you press the UIButton for -(id)initialize) 
//... 
decreaseTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(decrease) userInfo:nil repeats:YES]; 
//... 
} 
-(void)comept3 { //Gets calles when you rubbed the screen a bit 
    if ([timerCountSeconds isValid]) { 
    [timerCountSeconds invalidate]; 
    } 
} 

Cosa ho fatto di sbagliato? Puoi aiutarmi per favore?

+0

hai inizializzato TimerCountSeconds e DecreaseTimer? – olliej

+0

Li ho dichiarati nel file di intestazione ... li ho inizializzati nei metodi "touchesEnded" e "touchesBegan" – esanits

+0

Mostra altro codice. Inoltre, avere nomi come "DecreaseTimer" per variabili di istanza è generalmente una pessima idea. I nomi che iniziano con una lettera maiuscola vengono utilizzati per le classi e le strutture. Prendi in considerazione l'utilizzo di uno stile coerente consigliato da Apple. –

risposta

21

è necessario impostare un oggetto NSTimer-nil dopo invalidate, dal momento che la chiamata invalidate metodo fa anche un release (come per la documentazione di Apple). Se non lo fai, chiamare un metodo su di esso come isValid potrebbe causare il crash.

+1

Douple up-vote - ha cercato questo problema per ore ... Btw .: Potrebbe essere * molto * ragionevole conservare il NSTimer se è stato verificato altrove con isValid. Se non viene mantenuto, potrebbe essere rilasciato automaticamente una volta sparato (vedere anche la risposta di Chuck). – BurninLeo

0

È necessario inizializzare effettivamente i membri TimerCountSeconds e DecreaseTimer in fase di inizializzazione. Dando per scontato Non Sei il flusso di controllo è:

... 
myObject = [[MyObject alloc] initialize]; 
... 
[myObject touchesBegan:...] 
... 
[myObject touchesEnded:...] 
... 

Poi, quando si chiama initializeTimerCountSeconds non è stata inizializzata, in modo che stai facendo logicamente

[<random pointer> isValid] 

che andrà in crash. Analogamente, DecreaseTimer non è valido la prima volta che si chiama touchBegan.

Nel metodo di inizializzazione è necessario inizializzare effettivamente tutto, prima di tentare di utilizzare qualsiasi cosa.

È sembrano anche essere perdite timer (touchesBegin invalida il timer, ma non rilasciarlo)

+1

Se queste sono variabili di istanza, non sono "puntatori casuali" - loro " re nil. – Chuck

3

Molto probabilmente il timer memorizzato nella variabile che è già stato deallocato. Devi mantenerlo se vuoi tenerlo in giro per un tempo arbitrariamente lungo.

+0

quando sarà deallocato? quindi quando devo mantenerlo? – esanits

+0

Sarà deallocato quando il runloop decide di poter essere deallocato.Se vuoi tenerlo in giro, dovresti tenerlo quando lo metti da qualche parte, come con qualsiasi altro oggetto. – Chuck

+0

ok penso di aver capito;) l'ho trattenuto dopo l'inizializzazione ... ora non si blocca più :) è corretto? – esanits

3
[objTimer retain]; 

Quindi non si arresta in qualsiasi momento. Utilizzare questo dopo aver inizializzato il timer in modo che funzioni bene ....

0

È necessario impostare il timer nella discussione principale. NSTimer non verrà licenziato in thread in background.

  • objc:

    dispatch_async(dispatch_get_main_queue(), ^{ 
        _timer = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(YOUR_METHOD) userInfo:nil repeats:YES]; 
    }); 
    
  • Swift:

    dispatch_async(dispatch_get_main_queue()) { 
        timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "YOUR_METHOD", userInfo: nil, repeats: true) 
    } 
    
Problemi correlati