执行此代码时:
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
我是否需要将其取消或释放它,无论内存管理是什么?
我正在使用ARC
答案 0 :(得分:31)
是的,NSTimer
将保留对target
的强引用,这可能会导致(特别是在重复计时器中)强引用周期(例如,保留周期)。但是,在您的示例中,计时器不会重复,并且仅延迟0.5,因此在最坏的情况下,您将拥有一个强大的参考周期,该周期将在0.5秒内自动解决。
但是,未解决的强引用周期的一个常见示例是,UIViewController
具有重复的NSTimer
属性,但因为NSTimer
具有对{{UIViewController
的强引用1}},控制器最终会被保留。
因此,如果您将NSTimer
保留为实例变量,那么,是的,您应该invalidate
来解决强引用周期。如果您只是调用scheduledTimerWithTimeInterval
,而不是将其保存到实例变量(正如您可能从您的示例中推断出来的那样),那么当NSTimer
完成时,您的强引用周期将得到解决。
顺便说一句,如果您正在处理重复NSTimers
,请不要在invalidate
所有者的dealloc
中尝试NSTimer
因为dealloc
显然,在强参考周期解决之前,不会调用UIViewController
。例如,对于viewDidDisappear
,您可以在NSTimer
中执行此操作。
顺便说一句,Advanced Memory Management Programming Guide解释了强大的参考周期。显然,这是在他们描述正确使用弱引用的部分,这在这里不适用(因为你无法控制NSTimer
使用对目标的强引用这一事实),但它确实很好地解释了强参考周期的概念。
如果您不希望self
强烈引用weakSelf
,则在macOS 10.12和iOS 10或更高版本中,您可以使用块再现,然后使用{{1模式:
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
块中。
答案 1 :(得分:2)
如果你将它保存在属性中,那么是的,你需要在它触发选择器后将其设置为nil。
保存它也是安全的,以防你的课程由于某种原因被解除分配,以便你可以[timer invalidate]
(如果需要)。
答案 2 :(得分:1)
是的,您可以使用:myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
然后在你的viewDidDisappear [myTimer invalidate]
答案 3 :(得分:1)
使用使用闭包的Timer新方法
val enumerator = Enumerator.outputStream { os =>
val zip = new ZipOutputStream(os);
zip.putNextEntry(new ZipEntry("test.txt"))
Range(0, 100).map { i =>
zip.write("Here are 100000 random numbers:\n".map(_.toByte).toArray)
}
zip.closeEntry()
zip.close()
}
Ok.chunked(enumerator >>> Enumerator.eof)
.withHeaders("Content-Type"->"application/zip" ,
"Content-Disposition"->"attachment; filename=test.zip")