Skip to content

Instantly share code, notes, and snippets.

@janodev
Last active December 17, 2015 07:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janodev/5575264 to your computer and use it in GitHub Desktop.
Save janodev/5575264 to your computer and use it in GitHub Desktop.
NSTimer with safe release. Credits to Effective Objective-C 2.0.
int main(int argc, char *argv[]) {
@autoreleasepool {
TimerExample *timer = [TimerExample new];
[timer startTicking];
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:5];
while ([timeout timeIntervalSinceNow]>0) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
[timer stopTicking];
}
}
#import <Foundation/Foundation.h>
@interface NSTimer (BlockSupport)
+ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats;
@end
@implementation NSTimer (BlockSupport)
+ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval
// The class will be retained, not the instance.
// The Class object is a singleton so it doesn't matter.
target:self
selector:@selector(blockInvoke:)
// userInfo is retained while the block is valid
userInfo:[block copy] // make it a heap block
repeats:repeats];
}
+ (void)blockInvoke:(NSTimer*)timer {
void (^block)() = timer.userInfo;
if (block) {
block();
}
}
@end
// This example class retains NSTimer as an instance variable.
// NSTimer only retains self inside the block and only during the block duration.
// If the instance of the class is released, the timer is invalidated and released,
// and the class is deallocated as soon as the block is not running.
// If timer is not invalidated in the class dealloc:
// - the class and its NSTimer instance gets released,
// - the timer is not released because retainCount won't be 0 while it is valid,
// - the timer won't call anything because the __weak variable will be nil.
@interface TimerExample : NSObject
- (void)startTicking;
- (void)stopTicking;
@end
@implementation TimerExample {
NSTimer *_tickTimer;
}
- (id)init {
return [super init];
}
- (void)dealloc {
[_tickTimer invalidate];
}
- (void)stopTicking {
[_tickTimer invalidate];
_tickTimer = nil;
}
- (void)startTicking {
__weak TimerExample *weakSelf = self; // avoids retain
_tickTimer = [NSTimer
scheduledTimerWithTimeInterval:1.0
block:^{
// Creates a strong reference to keep the
// instance alive for the duration of the block.
// If class is deallocated and timer is not invalidated, weakSelf will be nil.
TimerExample *strongSelf = weakSelf;
[strongSelf tick];
}
repeats:YES];
}
- (void)tick {
NSLog(@"poll");
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment