NSTimer падает, когда я вызываю [Timer isValid] или [Timer invalidate] - PullRequest
10 голосов
/ 11 сентября 2010

У меня в приложении для iPhone два NSTimers.DecreaseTimer работает нормально, но TimerCountSeconds падает, когда я вызываю [timerCountSeconds isValid] или [timerCountSeconds 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];
    }
}

Что я сделал не так?Можете ли вы помочь мне?

Ответы [ 5 ]

22 голосов
/ 12 сентября 2010

Вы должны установить NSTimer объект на nil после того, как вы invalidate его, так как вызов метода invalidate также делает release (согласно документации Apple). Если вы этого не сделаете, вызов такого метода, как isValid, может привести к сбою.

3 голосов
/ 06 октября 2012
 [objTimer retain];

Тогда он никогда не рухнет. Используйте это после инициализации таймера, чтобы он работал нормально ....

3 голосов
/ 12 сентября 2010

Скорее всего, таймер, хранящийся в этой переменной, уже освобожден.Вам нужно сохранить его, если вы хотите хранить его как угодно долго.

1 голос
/ 30 августа 2016

Вам необходимо установить таймер в главном потоке. NSTimer не будет запущен в фоновом потоке.

  • 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)
    }
    
0 голосов
/ 12 сентября 2010

Вы должны на самом деле инициализировать TimerCountSeconds и DecreaseTimer членов в инициализации. Предполагая, что вы управляете потоком:

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

Тогда когда вы звоните initialize TimerCountSeconds не был инициализирован, так что вы логически делаете

[<random pointer> isValid]

Который потерпит крах. Точно так же DecreaseTimer недействителен при первом вызове touchesBegan.

В вашем методе инициализации вам нужно будет на самом деле инициализировать все, прежде чем пытаться что-либо использовать.

Похоже, у вас также есть утечка таймеров (touchesBegin делает таймер недействительным, но не освобождает его)

...