当我执行这段代码时:
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
我需要将其设为nil或释放它,或者做其他内存管理吗?
我正在使用ARC。
当我执行这段代码时:
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
我需要将其设为nil或释放它,或者做其他内存管理吗?
我正在使用ARC。
是的,NSTimer
会对target
保持强引用,这可能会导致强引用循环(即保留循环),尤其是在重复的计时器中。但在您的示例中,计时器不会重复,并且仅延迟0.5秒,因此最坏的情况是在0.5秒后自动解决强引用循环。
但一个常见的未解决的强引用循环的例子是,有一个重复的NSTimer
属性的UIViewController
,因为NSTimer
对UIViewController
保持强引用,所以控制器将被保留。
因此,如果您将NSTimer
作为实例变量保留,则应该使用invalidate
来解决强引用循环。如果您只调用了scheduledTimerWithTimeInterval
,但没有将其保存到实例变量中(如您的示例所示),则当NSTimer
完成时,您的强引用循环将被解决。
顺便提一下,如果你正在处理重复的NSTimers
,不要试图在NSTimer
所有者的dealloc
中使它们失效,因为显然直到强引用循环被解决之前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];
[timer invalidate]
。weak
,你就不必自己将其设为nil
。在它触发后(假设它是非重复的),它会自动释放。 - Robinvalidate
变得必要。否则,运行循环将保留其指针指向弱引用计时器的视图控制器。 - mfaani是的,您可以使用:myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
然后在您的viewDidDisappear中使用[myTimer invalidate]
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()
})
viewWillDisappear
中invalidate
,那么你必须这样做。(顺便说一下,你不必将私有 ivars 放在 .h 文件中;私有类扩展更好。)还有几次你提到设置NSTimer
为nil
。请注意,这并不能解决强引用循环的问题。计时器要么需要完成(而不是重复),要么你需要使用新的 ivar 进行invalidate
。 - Robnil
并执行if timer!= nil
或者只需执行!timer.isValid
即可?换句话说,是否有必要执行timer = nil
?在您之前的评论中,您已经说过这与内存管理无关,因此我想知道为什么许多开发人员仍然这样做,而isValid
可以增加清晰度... - mfaani