NSTimer аварийно завершает работу, когда я вызываю [Timer isValid] или [Timer недействителен]

У меня есть два NSTimers в моем приложении для iPhone. 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];
    }
}

Что я сделал не так? Не могли бы вы мне помочь?


person esanits    schedule 11.09.2010    source источник
comment
Вы инициализировали TimerCountSeconds и DecreaseTimer?   -  person olliej    schedule 11.09.2010
comment
Я объявил их в заголовочном файле... Я инициализировал их в методах touchesEnded и touchesBegan   -  person esanits    schedule 11.09.2010
comment
Показать больше кода. Кроме того, иметь такие имена, как DecreaseTimer для переменных экземпляра, как правило, очень плохая идея. Имена, начинающиеся с заглавной буквы, используются для классов и структур. Рассмотрите возможность использования последовательного стиля, который поддерживает Apple.   -  person Stefan Arentz    schedule 11.09.2010
comment
хорошо, я изменил имена переменных... я забыл ввести метод comept3... это, вероятно, поможет вам помочь мне;)   -  person esanits    schedule 12.09.2010


Ответы (5)


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

person Shaggy Frog    schedule 11.09.2010
comment
Двойное голосование - искал эту проблему часами... Кстати: может быть очень разумно сохранить NSTimer, если он проверен в другом месте с помощью isValid. Если его не сохранить, он может автоматически сбрасываться при выстреле (см. также ответ Чака). - person BurninLeo; 03.03.2013

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

person Chuck    schedule 11.09.2010
comment
когда он будет освобожден? так когда я должен сохранить его? - person esanits; 12.09.2010
comment
Он будет освобожден, когда цикл выполнения решит, что его можно освободить. Если вы хотите сохранить его, вы должны сохранить его, когда будете где-то хранить, как и любой другой объект. - person Chuck; 12.09.2010
comment
хорошо, кажется, я понял ;) я сохранил его после инициализации... теперь он больше не вылетает :) это правильно? - person esanits; 12.09.2010

 [objTimer retain];

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

person jayesh kavathiya    schedule 06.10.2012

Вам нужно установить таймер в основном потоке. NSTimer не будет запускаться в фоновом потоке.

  • Объект:

    dispatch_async(dispatch_get_main_queue(), ^{
       _timer = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(YOUR_METHOD) userInfo:nil repeats:YES];
    });
    
  • Быстрый:

    dispatch_async(dispatch_get_main_queue()) {
       timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "YOUR_METHOD", userInfo: nil, repeats: true)
    }
    
person zzzz    schedule 30.08.2016

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

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

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

[<random pointer> isValid]

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

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

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

person olliej    schedule 11.09.2010
comment
Если это переменные экземпляра, они не являются случайными указателями — они равны нулю. - person Chuck; 12.09.2010