NSTimer memory management
ios, nstimer, strong-references
Solution
Yes, `NSTimer` will maintain a strong reference to the `target`, which can cause (especially in repeating timers) strong reference cycles (a.k.a. retain cycles). In your example, though, the timer does not repeat, and is delayed only 0.5, so worst case scenario, you will have a strong reference cycle that will automatically resolve itself in 0.5 seconds.
But a common example of an unresolved strong reference cycle would be to have a `UIViewController` with a `NSTimer` property that repeats, but because the `NSTimer` has a strong reference to the `UIViewController`, the controller will end up being retained.
So, if you're keeping the `NSTimer` as an instance variable, then, yes, you should `invalidate` it, to resolve the strong reference cycle. If you're just calling the `scheduledTimerWithTimeInterval`, but not saving it to an instance variable (as one might infer from your example), then your strong reference cycle will be resolved when the `NSTimer` is complete.
And, by the way, if you're dealing with repeating `NSTimers`, don't try to `invalidate` them in `dealloc` of the owner of the `NSTimer` because the `dealloc` obviously will not be called until the strong reference cycle is resolved. In the case of a `UIViewController`, for example, you might do it in `viewDidDisappear`.
By the way, the Advanced Memory Management Programming Guide explains what strong reference cycles are. Clearly, this is in a section where they're describing the proper use of weak references, which isn't applicable here (because you have no control over the fact that `NSTimer` uses strong references to the target), but it does explain the concepts of strong reference cycles nicely.
If you don't want your `NSTimer` to keep a strong reference to `self`, in macOS 10.12 and iOS 10, or later, you can use the block rendition and then use the `weakSelf` pattern:
typeof(self) __weak weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:0.5 repeats:false block:^(NSTimer * _Nonnull timer) {
[weakSelf showButtons];
}];
By the way, I notice that you're calling `showButtons`. If you're trying to just show some controls on your view, you could eliminate the use of the `NSTimer` altogether and do something like:
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];
This doesn't suffer the retain issues of `NSTimer` objects, and performs both the delay as well as the graceful showing of the button(s) all in one statement. If you're doing additional processing in your `showButtons` method, you can put that in the `completion` block.
Problem
When I execute this code: ``` [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; ``` do I need to nil it or release it, ot whatever for memory management? I am using ARC