14

当我执行此代码时:

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];

我是否需要将它归零或释放它,或者用于内存管理?

我正在使用 ARC

4

4 回答 4

35

是的,NSTimer将保持对 的强引用target,这可能会导致(尤其是在重复计时器中)强引用周期(又名保留周期)。但是,在您的示例中,计时器不会重复,并且仅延迟 0.5,因此在最坏的情况下,您将拥有一个强大的参考周期,它将在 0.5 秒内自动解决。

但是一个未解决的强引用循环的常见示例是具有重复UIViewControllerNSTimer属性,但由于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块中。

于 2012-11-23T19:25:25.730 回答
2

如果您将它保存在属性中,那么是的,您确实需要在触发选择器后将其设置为 nil。

保存它也是安全的,以防您的班级因任何原因被释放,以便您可以[timer invalidate]在需要时进行。

于 2012-11-23T19:16:45.970 回答
1

是的,你可以使用:myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; 然后在你的 viewDidDisappear[myTimer invalidate]

于 2012-11-23T19:36:10.133 回答
1

使用使用闭包的 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()
})
于 2019-05-24T10:25:01.260 回答