iosobjective-cnstimerdealloc

NSTimer with weak self; why is dealloc not called?


Consider view controller with strong(or weak, the same) NSTimer property:

__weak __typeof(self) ws = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:ws selector:@selector(timerTigger:) userInfo:nil repeats:YES];

But why does this view controller not invoke dealloc method, whether I pass strong or weak reference to self?

Here is the detailed code:

#import "SecondViewController.h"

@interface SecondViewController ()

@property (nonatomic, weak) NSTimer *timer;

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    __weak __typeof(self) ws = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:ws selector:@selector(timerTigger:) userInfo:nil repeats:YES];

}

- (void)timerTigger:(id)timer {
    NSLog(@"do someting");
}

- (void)dealloc {
    NSLog(@"SecondViewController dealloc");
}

Solution

  • NSTimer maintains strong reference to its target until the timer is invalidated. You don't get to choose whether NSTimer establishes a weak or strong reference. When you pass a weak reference, as long as ws is not nil by the time you start the timer (which it obviously won't be, in this case), NSTimer will establish a strong reference to whatever target pointed. Whether scheduledTimerWithTimeInterval establishes a strong or weak reference is not some inherent characteristic of the pointer that you passed to it, but rather a question of what that method does with that pointer it was provided.

    To fix this strong reference behavior, you can adopt one of the following patterns: