NSTimer не останавливается - PullRequest
22 голосов
/ 23 июня 2009

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

Вот мой код:

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");
}

Ответы [ 12 ]

38 голосов
/ 17 ноября 2009

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

timer = [ [NSTimer scheduledTimerWithTimeInterval: ...] retain];
...
...
[timer invalidate];
[timer release];
14 голосов
/ 28 октября 2012

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

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

[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];        
    }
}

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

6 голосов
/ 23 июня 2009

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

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

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

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

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

и способ

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

Надеюсь, это поможет

2 голосов
/ 23 июня 2009

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

- (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 и убедитесь, что она вызывается!

1 голос
/ 21 июля 2016

Это помогло мне в Swift

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

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

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

    })

}
1 голос
/ 20 марта 2012
**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;
0 голосов
/ 12 ноября 2015

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

dispatch_async(dispatch_get_main_queue(), ^{
    [timer invalidate];
});
0 голосов
/ 27 апреля 2015

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

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

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

0 голосов
/ 28 мая 2013

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

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

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

0 голосов
/ 23 декабря 2010

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...