在 UIViewController 中使 NSTimer 无效以避免保留周期的最佳时间 [英] Best time to invalidate NSTimer inside UIViewController to avoid retain cycle

查看:28
本文介绍了在 UIViewController 中使 NSTimer 无效以避免保留周期的最佳时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道什么时候停止在 UIViewController 内保持引用的 NSTimer 的最佳时间,以避免计时器和控制器之间的保留循环?

这里有更详细的问题:我在 UIViewController 中有一个 NSTimer.

在视图控制器的 ViewDidLoad 期间,我启动计时器:

statusTimer = [NSTimer scheduleTimerWithTimeInterval: 1 target: self selector: @selector(updateStatus) userInfo: nil repeats: YES];

以上导致计时器持有对视图控制器的引用.

现在我想释放我的控制器(例如父控制器释放它)

问题是:在哪里可以调用[statusTimer invalidate]来强制定时器释放对控制器的引用?

我尝试将它放在 ViewDidUnload 中,但是在视图收到内存警告之前不会触发它,所以不是一个好地方.我尝试过 dealloc,但只要计时器还活着(鸡和蛋问题),dealloc 就永远不会被调用.

有什么好的建议吗?

解决方案

  1. 你可以避免保留周期,例如,将计时器对准一个持有非保留(弱)引用的 StatusUpdate 对象到您的控制器,或者通过使用一个指针初始化您的控制器的 StatusUpdater,持有对其的弱引用,并为您设置计时器.

    • 当目标窗口为 nil(它应该处理您提供的 -viewDidDisappear: 以及 -viewDidDisappear: 的反例.这确实意味着您的视图正在返回到您的控制器;您可以避免通过向控制器发送 -view:willMoveToWindow: 消息或发布通知(如果您愿意)来避免获取计时器.

    • 大概是您导致视图从窗口中移除,因此您可以在驱逐视图的行旁边添加一行来停止计时器.p>

    • 您可以使用非重复计时器.它一触发就会失效.然后您可以在回调中测试是否应该创建一个新的非重复计时器,如果是,则创建它.不需要的保留周期只会将计时器和控制器对保留到下一个触发日期.只需 1 秒的触发日期,您就不必担心.

除了第一个建议之外的每一个建议都是一种适应保留周期并在适当的时间打破它的方法.第一个建议实际上避免了保留周期.

Does any one know when is the best time to stop an NSTimer that is held reference inside of a UIViewController to avoid retain cycle between the timer and the controller?

Here is the question in more details: I have an NSTimer inside of a UIViewController.

During ViewDidLoad of the view controller, I start the timer:

statusTimer = [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector: @selector(updateStatus) userInfo: nil repeats: YES];

The above causes the timer to hold a reference to the view controller.

Now I want to release my controller (parent controller releases it for example)

the question is: where can I put the call to [statusTimer invalidate] to force the timer to release the reference to the controller?

I tried putting it in ViewDidUnload, but that does not get fired until the view receives a memory warning, so not a good place. I tried dealloc, but dealloc will never get called as long as the timer is alive (chicken & egg problem).

Any good suggestions?

解决方案

  1. You could avoid the retain cycle to begin with by, e.g., aiming the timer at a StatusUpdate object that holds a non-retained (weak) reference to your controller, or by having a StatusUpdater that is initialized with a pointer your controller, holds a weak reference to that, and sets up the timer for you.

    • You could have the view stop the timer in -willMoveToWindow: when the target window is nil (which should handle the counterexample to -viewDidDisappear: that you provided) as well as in -viewDidDisappear:. This does mean your view is reaching back into your controller; you could avoid reaching in to grab the timer by just send the controller a -view:willMoveToWindow: message or by posting a notification, if you care.

    • Presumably, you're the one causing the view to be removed from the window, so you could add a line to stop the timer alongside the line that evicts the view.

    • You could use a non-repeating timer. It will invalidate as soon as it fires. You can then test in the callback whether a new non-repeating timer should be created, and, if so, create it. The unwanted retain cycle will then only keep the timer and controller pair around till the next fire date. With a 1 second fire date, you wouldn't have much to worry about.

Every suggestion but the first is a way to live with the retain cycle and break it at the appropriate time. The first suggestion actually avoids the retain cycle.

这篇关于在 UIViewController 中使 NSTimer 无效以避免保留周期的最佳时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆