Управление памятью 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]