当我执行此代码时:
[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
,这可能会导致(尤其是在重复计时器中)强引用周期(又名保留周期)。但是,在您的示例中,计时器不会重复,并且仅延迟 0.5,因此在最坏的情况下,您将拥有一个强大的参考周期,它将在 0.5 秒内自动解决。
但是一个未解决的强引用循环的常见示例是具有重复UIViewController
的NSTimer
属性,但由于NSTimer
具有对 的强引用UIViewController
,控制器最终将被保留。
因此,如果您将 保留NSTimer
为实例变量,那么,是的,您应该invalidate
使用它来解决强引用循环。如果您只是调用scheduledTimerWithTimeInterval
,但没有将其保存到实例变量中(可能从您的示例中推断出),那么当NSTimer
完成时,您的强引用循环将得到解决。
而且,顺便说一句,如果您正在处理重复NSTimers
,请不要尝试将invalidate
它们归入dealloc
的所有者,NSTimer
因为在dealloc
解决强引用循环之前显然不会调用它们。例如,在 a 的情况下UIViewController
,您可以在viewDidDisappear
.
顺便说一句,高级内存管理编程指南解释了强引用周期是什么。显然,这是在他们描述正确使用弱引用的部分中,这在此处不适用(因为您无法控制对NSTimer
目标使用强引用的事实),但它确实解释了强参考循环很好。
如果您不想在 macOS 10.12 和 iOS 10 或更高版本NSTimer
中保留对 的强引用self
,您可以使用块再现,然后使用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
块中。
如果您将它保存在属性中,那么是的,您确实需要在触发选择器后将其设置为 nil。
保存它也是安全的,以防您的班级因任何原因被释放,以便您可以[timer invalidate]
在需要时进行。
是的,你可以使用:myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
然后在你的 viewDidDisappear[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()
})