NSTimer отключает деаллок в UIView - PullRequest
9 голосов
/ 15 апреля 2011
@interface someview:UIView{
  NSTimer* timer;
}
@end

@implementation someview

-(void)dealloc{
  NSLog(@"dealloc someview");
  [timer invalidate];
  timer = nil;
}
-(void)runTimer{
//
}
-(void)someMethod{

  timer = [NSTimer timerWithTimeInterval:2.0f target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}

@end

Выпуск someview НЕ вызовет dealloc, и таймер продолжает работать.

Если я закомментирую часть «timer = [NSTimer schedule ....», будет вызван dealloc. Это означает, что все остальные части моего кода работают должным образом, и виновником является таймер. Метод runTimer пуст, а это значит, что со мной просто таймер.

Ответы [ 3 ]

22 голосов
/ 19 мая 2011

Я думаю, что лучшее решение при использовании NSTimer внутри UIView - это переопределить метод removeFromSuperview;

- (void)removeFromSuperview
{
    [timer invalidate];
    timer = nil;

    [super removeFromSuperview];
}

Единственное, что нужно иметь в виду, это то, что вам нужно убедиться, что таймер необъект nil, потому что removeFromSuperview также может автоматически вызываться из других методов супер-деллока UIView.Вы можете проверить условное заверение.

14 голосов
/ 15 апреля 2011

NSTimer сохраняет цель.Следовательно, таймер должен быть аннулирован до того, как ваш вид будет обозначен как.

0 голосов
/ 18 декабря 2013

Как упоминалось выше, таймеры сохраняют свои цели. Пока таймер не станет недействительным, между таймером и представлением будет цикл сохранения, поэтому представление не будет освобождено.

Я бы объявил недействительным таймер, когда он был удален из иерархии представлений с помощью подкласса didMoveToSuperview, он вызывается системой при наличии изменений, связанных с представлением (например, изменения суперпредставления). 'RemoveFromSuperview' вызывается только тогда, когда removeFromSuperview вызывается в UIView

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];

    if (!self.superview)
    {
        [timer invalidate];
        timer = nil;
    }
}
...