Как сделать таймер недействительным, если я не создаю объект NSTimer

Я не хочу создавать объект NSTimer. Как сделать таймер недействительным? Я хочу аннулировать таймер в viewWillDisappear.

-(void) viewDidLoad
{ 
 [super viewDidLoad];
 [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(onTimer:) userInfo:nil repeats:YES];
}

person Voloda2    schedule 30.08.2012    source источник
comment
Что вы подразумеваете под я не хочу создавать объект NSTimer? Вы уже создали его, используя scheduledTimerWithTimeInterval.   -  person sch    schedule 30.08.2012
comment
Я имею в виду, что я не держусь за таймер, который я создаю. Является ли это возможным?   -  person Voloda2    schedule 30.08.2012


Ответы (4)


А

вы должны держаться за таймер, который вы создаете:

@interface MONObject ()
@property (nonatomic, retain) NSTimer * timerIvar;
@end

@implementation MONObject
...
- (void)viewDidLoad
{ 
 [super viewDidLoad];
 self.timerIvar = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(onTimer:) userInfo:nil repeats:YES];
}

- (void)invalidateTimer
{
  [self.timerIvar invalidate];
  self.timerIvar = nil;
}

- (void)viewWillDisappear:(BOOL)animated
{
  ...
  [self invalidateTimer];
}

Б

другим вариантом может быть аннулирование таймера, переданного в обратном вызове, но это не произойдет в пределах viewDidUnload:. следовательно, это не совсем применимо в этом сценарии:

- (void)onTimer:(NSTimer *)pTimer
{
  [pTimer invalidate];
}
person justin    schedule 30.08.2012

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

Сохранение ссылки на таймер — правильный способ сделать это, но для полноты вы также можете использовать метод -performSelector:withObject:afterDelay: в качестве таймера бедняка. Этот вызов может быть признан недействительным с помощью +cancelPreviousPerformRequestsWithTarget:. Образец кода:

- (void) viewDidLoad
{
    [super viewDidLoad];
    [self performSelector:@selector(timerTick) withObject:nil afterDelay:10];
}

А потом:

- (void) viewWillDisappear
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [super viewWillDisappear];
}

Но это неправильный способ сделать это, потому что могут быть другие запросы селектора выполнения, ожидающие вашего объекта, которые вы бы отменили. Лучше всего держать таймер рядом, чтобы вы точно знали, что отменяете.

Кстати, запускать таймер в -viewDidLoad тоже наверное плохая идея. Загрузка представления может произойти в любое время, независимо от отображаемого представления.

person zoul    schedule 30.08.2012

Возможно, этот метод может помочь вам:

[self performSelector:@selector(onTimer:) withObject:nil afterDelay:10];
person Mil0R3    schedule 30.08.2012

Если вы не хотите удерживать свой таймер, объект NSTimer будет передан методу таймера (в вашем случае onTimer:), поэтому в этом методе вы можете проверить, нужен ли еще таймер, и сделать его недействительным. Однако у вас возникнут проблемы, если представление вернется до того, как вы аннулируете таймер и создадите новый.

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

@property (readwrite, nonatomic) BOOL hasTimer;

getter возвращает YES, если таймер не равен нулю, setter делает таймер недействительным или создает новый.

person gnasher729    schedule 24.02.2014