2010-09-11 12 views
9

Tengo dos NSTimers en mi aplicación de iPhone. DecreaseTimer funciona bien, pero TimerCountSeconds se bloquea cuando llamo a [timerCountSeconds isValid] o [timerCountSeconds invalida]. Se usan así:NSTimer falla, cuando llamo a [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]; 
    } 
} 

¿Qué hice mal? ¿Puedes ayudarme?

+0

has inicializado TimerCountSeconds y DecreaseTimer? – olliej

+0

Los declare en el archivo de encabezado ... Los inicié en los métodos "touchesEnded" y "touchesBegan" – esanits

+0

Mostrar más código. Además, tener nombres como 'DecreaseTimer' por ejemplo, variables es generalmente una muy mala idea. Los nombres que comienzan con una letra mayúscula se usan para clases y estructuras. Considere usar un estilo consistente que Apple defiende. –

Respuesta

21

Es necesario configurar un objeto NSTimer-nil después invalidate, ya que la llamada invalidate método también hace un release (según la documentación de Apple). Si no lo hace, llamar a un método como isValid podría causar su bloqueo.

+1

Douple up-vote: buscó este problema durante horas ... Por cierto: puede ser * muy * razonable conservar el NSTimer si se verifica en otro lugar con isValid. Si no se retiene, puede soltarse automáticamente cuando se dispare (también vea la respuesta de Chuck). – BurninLeo

0

Necesita inicializar realmente los miembros TimerCountSeconds y DecreaseTimer en inicialización. Suponiendo que No Eres flujo de control es:

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

Luego, cuando se llama a initializeTimerCountSeconds no se ha inicializado, por lo que está haciendo lógicamente

[<random pointer> isValid] 

que hará que colapse. De forma similar, DecreaseTimer no es válido la primera vez que llama a touchesBegan.

En su método de inicialización tendrá que inicializar todo, antes de intentar usar algo.

También parece que tienen fugas temporizadores (touchesBegin invalida el temporizador pero no lo libera)

+1

Si estas son variables de instancia, no son "punteros aleatorios" - ellos ' re nil. – Chuck

3

Lo más probable es que el temporizador almacenado en esa variable ya ha sido desasignado. Debe conservarlo si desea mantenerlo durante un tiempo arbitrariamente largo.

+0

¿cuándo será desasignado? Entonces, ¿cuándo debo retenerlo? – esanits

+0

Será desasignado cuando el runloop decida que puede ser desasignado.Si desea mantenerlo, debe conservarlo cuando lo guarde en algún lugar, como con cualquier otro objeto. – Chuck

+0

bien, creo que entendí;) lo conservé después de la inicialización ... ahora ya no se cuelga :) ¿es correcto? – esanits

3
[objTimer retain]; 

Luego no se bloqueará en ningún momento. Úselo después de inicializar el temporizador para que funcione bien ...

0

Debe configurar el temporizador en el hilo principal. NSTimer no se disparará en el hilo de fondo.

  • 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) 
    }