The whole problem with the selector-based NSTimer method is that it sets up a strong reference to the object you pass to it. So, whether the variable that you used to bind to the target that you passed to scheduledTimerWithTimeInterval is unimportant, strong or weak. Assuming the target link was not nil by the time the scheduled selector-based timer was scheduled, NSTimer set its own strong link. The โweakโ and โstrongโ nature of the links in the calling code only dictates where the ARC will place its own memory management calls in the callerโs code, but target is just a simple pointer, and not one of these weak and strong data is passed to NSTimer . The selector NSTimer will set its own strong link, which will not be resolved until the timer is invalidated .
That's why when we want to invalidate a timer created using a selector-based method, we should use it in viewDidDisappear or the like, not dealloc .
Note. scheduledTimerWithTimeInterval now has block-based variations for iOS 10 and later, so you can enjoy a weak reference block template if you don't need to support earlier versions of iOS:
typeof(self) __weak weakSelf = self; [NSTimer scheduledTimerWithTimeInterval:30 repeats:true block:^(NSTimer * _Nonnull timer) {
source share