Когда я выполняю этот код:
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
Нужно ли это использовать или освободить его, независимо от управления памятью?
Я использую ARC
Когда я выполняю этот код:
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
Нужно ли это использовать или освободить его, независимо от управления памятью?
Я использую ARC
Да, NSTimer
будет поддерживать сильную ссылку на target
, что может привести к сильным опорным циклам (особенно в повторяющихся таймерах) (циклы сохранения a.k.a.). В вашем примере, тем не менее, таймер не повторяется и задерживается только на 0,5, поэтому в худшем случае у вас будет сильный опорный цикл, который автоматически разрешит себя через 0,5 секунды.
Но общий пример нерешенного сильного опорного цикла будет иметь UIViewController
со свойством NSTimer
, который повторяется, но потому, что NSTimer
имеет сильную ссылку на UIViewController
, контроллер закончится сохраняются.
Итак, если вы сохраняете NSTimer
как переменную экземпляра, то да, вы должны invalidate
it, чтобы решить сильный ссылочный цикл. Если вы просто вызываете scheduledTimerWithTimeInterval
, но не сохраняете его в переменной экземпляра (как можно было бы сделать вывод из вашего примера), тогда ваш сильный ссылочный цикл будет разрешен, когда NSTimer
будет завершен.
И, кстати, если вы имеете дело с повторением NSTimers
, не пытайтесь invalidate
их в dealloc
владельца NSTimer
, потому что dealloc
явно не будет до тех пор, пока не будет разрешен сильный опорный цикл. Например, в случае 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];
И затем в вашем представленииDidDisappear [myTimer invalidate]
Используйте новый метод Timer, который использует замыкания
timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: {[weak self] (timer) in
print("Tick tock")
guard let ws = self else { return }
//some action that repeats
ws.myViewControllerMethod()
})