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];
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.