2009-06-23 3 views
22

У меня есть таймер, который срабатывает при вызове метода viewWillAppear и недействителен при вызове метода viewDidDisappear. Но после определенного переключения между видами таймер продолжает стрелять даже после того, как он был признан недействительным. В чем проблема?NSTimer не останавливается

Вот мой код:

NSTimer *timer; 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    timer = [NSTimer scheduledTimerWithTimeInterval: 0.2f 
        target: self 
        selector:@selector(timerAction) 
        userInfo:nil 
        repeats:YES]; 
} 

-(void)viewDidDisappear:(BOOL)animated { 
    [super viewDidDisappear:animated]; 
    [timer invalidate]; 
    timer = nil; 
} 

-(void) timerAction 
{ 
    NSLog(@"timerAction"); 
} 

ответ

37

Я должен был держать ссылку на таймер, сохраняя его. :) Я задал этот вопрос 5 месяцев назад, и это потрясающе, насколько больше опыта я приобрел. :)

timer = [ [NSTimer scheduledTimerWithTimeInterval: ...] retain]; 
... 
... 
[timer invalidate]; 
[timer release]; 
+0

Как это сделать в ARC, когда 'keep' и' release' не разрешены? –

+1

Для iOS 7/8 см. Ответ ниже, используя пару таймеров 'repeat: NO'. –

0

Вы забыли выпустить таймер в viewWillDisappear:

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
    [timer invalidate]; 
    [timer release]; 
    timer = nil; 
} 

Это не должно вызывать таймер, чтобы продолжать стрелять, хотя ...

+1

В этом случае приложение сокрушает, потому что таймер уже выпущен. –

+0

Здесь есть правильный ответ Бен Готов. Вы должны сохранить таймер после его создания, а затем сделать недействительным и отпустить его, когда хотите, чтобы он перестал вызывать вас. – rpetrich

+0

У вас нет/иметь /, чтобы сохранить его, поскольку цикл выполнения сделает это, но это хорошая идея, если вы хотите быть в безопасности. – Wevah

0

invalidatedoco говорит

«Цикл запуска удаляет и освобождает таймер, либо непосредственно перед возвратом метода invalidate, либо в какой-то более поздний момент».

Я полагаю, что ваше удаление удаляется в какой-то более поздний момент.

6

метод, названный с помощью таймера должно иметь определение

- (void)methodName:(NSTimer *)aTimer; 

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

Попробуйте изменить инициализации таймера

timer = [NSTimer scheduledTimerWithTimeInterval: 0.2f target: self selector:@selector(timerAction:) userInfo:nil repeats:YES] 

и метод для

-(void) timerAction:(NSTimer *)aTimer{...} 

Надежда, что помогает

+0

Это не будет иметь никакого эффекта. – rpetrich

+0

@ rpetrich Если вы можете дать еще меньше информации в своем ответе, это было бы отличным чуваком! –

+1

Недействительный объект таймера в методе и сделать его нулевым. Также убедитесь, что NSTimer объявлен как свойство сохранения. Это работает для меня. –

2

Это не может быть проблемой, но вам нужно сохранить ссылку на таймер, который возвращается из запланированногоTimerWithInterval :. Без этого указатель на таймер может оказаться недействительным к моменту его остановки.

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    timer = [[NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(timerAction) userInfo:nil repeats:YES] retain]; 
} 

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [timer invalidate]; 
    [timer release]; 
    timer = nil; 
    [super viewDidDisappear:animated]; 
} 

- (void)dealloc 
{ 
    [timer invalidate]; 
    [timer release]; 
    timer = nil; 
    [super dealloc]; 
} 

Также попробуйте установить точку останова в viewDidDisappear и убедитесь, что она вызвана!

0

У меня была та же проблема.

Я не могу dealloc мой экземпляр, если таймер еще работает, так что я должен остановить его перед вызовом:

- (void)stopTimer 
{ 
    [timer invalidate]; 
    [timer release]; 
    timer = nil; 
} 

После вызова этого метода мой таймер действительно остановить

1
**In .h class** 

@interface 
{ 
NSTimer * theTimer; 

} 


**in .m class** 

//put this code where you want to calling the NSTimer function 

     theTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateCounter:) userInfo:nil repeats:YES]; 



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

    // write your code here for counter update 

} 


// put this code to Stop timer: 

    [theTimer invalidate]; 
    theTimer = nil; 
14

Это является абсолютным решением.Ни один из них выше работал для меня, так что я сделал это,

, где вы хотите, чтобы запустить таймер,

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:NO]; 

Метод, вызовы таймера,

-(void)timerMethod 
{ 
    // do what you need to do 

    if (needs to be called again) { 

     [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:NO];   
    } 
} 

надеюсь, что это помогает ,

+2

Это единственное, что работает для меня также ... – Idan

+2

Действительно ... Похоже на ошибку Apple для меня. Недопустимый метод invalidate из-за значения повторения BOOL, установленного в YES, выглядит немного странным для меня – Plot

+2

Эта ошибка все еще существует в iOS8. Это единственный способ решить проблему. – Anil

0

- (void)viewWillAppear:(BOOL)animated вновь вызывается.

Фактически он вызывается каждый раз, когда вы переключаете представления или после отклонения модального вида. В принципе, каждый раз, когда ваш взгляд действительно появляется на экране, а не только в первый раз.

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

0

После создания таймера просто зарегистрировать его запустить в NSRunLoopCommonModes:

[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes];

Тогда invalidate метод будет работать.

0

Это работает для меня

dispatch_async(dispatch_get_main_queue(), ^{ 
    [timer invalidate]; 
}); 
1

Это сделал трюк для меня в Swift

override func viewWillDisappear(animated: Bool) { 
    super.viewWillDisappear(animated) 

    dispatch_async(dispatch_get_main_queue(),{ [weak self] in 

     self?.idleTimer?.invalidate() 
     self?.idleTimer = nil 

    }) 

} 
Смежные вопросы