Управление памятью NSTimer

когда я выполняю этот код:

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

нужно ли мне его обнулить или отпустить, что угодно для управления памятью?

Я использую ARC

3 ответов


да NSTimer будет поддерживать сильную ссылку на target, что может вызвать (особенно при повторении таймеров) сильные опорные циклы (a.к. a. сохранять циклы). Однако в вашем примере таймер не повторяется и задерживается только на 0,5, поэтому в худшем случае у вас будет сильный ссылочный цикл, который автоматически разрешится через 0,5 секунды.

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

Итак, если вы держите NSTimer как переменная экземпляра, тогда да, вы должны invalidate ИТ, разрешить сильный цикл ссылки. Если вы просто называете scheduledTimerWithTimeInterval, но не сохраняя его в переменной экземпляра (как можно было бы сделать из вашего примера), тогда ваш сильный ссылочный цикл будет разрешен, когда NSTimer завершено.

и, кстати, если вы имеете дело с повторением NSTimers, не пытайся invalidate их в dealloc владельца NSTimer, потому что dealloc очевидно, не будет вызываться, пока не будет разрешен сильный ссылочный цикл. В случае a UIViewController, например, вы можете сделать это viewDidDisappear.

кстати, Расширенное Руководство По Программированию Управления Памятью объясняет, что такое сильные опорные циклы. Ясно, что это в разделе, где они описывают правильное использование слабых ссылок, которое здесь неприменимо (потому что у вас нет контроля над тем, что NSTimer использует сильные ссылки на цель), но он хорошо объясняет концепции сильных ссылочных циклов.


если вы не хотите, чтобы ваш NSTimer сохранить сильную ссылку на self, в macOS 10.12 и iOS 10 или более поздней версии вы можете использовать представление блока, а затем использовать weakSelf шаблон:

typeof(self) __weak weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:0.5 repeats:false block:^(NSTimer * _Nonnull timer) {
    [weakSelf showButtons];
}];

по кстати, я заметил, что ты называешь showButtons. Если вы пытаетесь просто показать некоторые элементы управления в своем представлении, вы можете исключить использование NSTimer в целом и сделать что-то вроде:

self.button1.alpha = 0.0;
self.button2.alpha = 0.0;

[UIView animateWithDuration:0.25
                      delay:0.5
                    options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
                 animations:^{
                     self.button1.alpha = 1.0;
                     self.button2.alpha = 1.0;
                 }
                 completion:nil];

это не страдает от проблем сохранения NSTimer объекты и выполняет как задержку, так и изящное отображение кнопки(кнопок) в одном операторе. Если вы делаете дополнительную обработку в showButtons метод, вы можете поместить это в completion блок.


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

также безопасно сохранить его в случае, если ваш класс будет освобожден по какой-либо причине, так что вы можете [timer invalidate] Если вам нужно.


Да, вы можете использовать: myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; И тогда в вашем viewDidDisappear [myTimer invalidate]