The proposed code:
__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];
has the effect that (i) a weak reference is made to self; (ii) that weak reference is read in order to provide a pointer to NSTimer
. It won't have the effect of creating an NSTimer
with a weak reference. The only difference between that code and using a __strong
reference is that if self is deallocated in between the two lines given then you'll pass nil
to the timer.
The best thing you can do is create a proxy object. Something like:
[...]
@implementation BTWeakTimerTarget
{
__weak target;
SEL selector;
}
[...]
- (void)timerDidFire:(NSTimer *)timer
{
if(target)
{
[target performSelector:selector withObject:timer];
}
else
{
[timer invalidate];
}
}
@end
Then you'd do something like:
BTWeakTimerTarget *target = [[BTWeakTimerTarget alloc] initWithTarget:self selector:@selector(tick)];
timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:target selector:@selector(timerDidFire:) ...];
Or even add a class method to BTWeakTimerTarget of the form +scheduledTimerWithTimeInterval:target:selector:...
to create a neater form of that code. You'll probably want to expose the real NSTimer
so that you can invalidate
it, otherwise the rules established will be:
- the real target isn't retained by the timer;
- the timer will fire once after the real target has begun (and probably completed) deallocation, but that firing will be ignored and the timer invalidated then.