Re: Circular references caused by scheduled NSTimers?
Re: Circular references caused by scheduled NSTimers?
- Subject: Re: Circular references caused by scheduled NSTimers?
- From: Graham Cox <email@hidden>
- Date: Fri, 19 Apr 2013 16:53:17 +1000
On 19/04/2013, at 4:35 PM, Greg Parker <email@hidden> wrote:
> Another solution is to introduce a weak reference between the timer and your controller. Create a helper class that holds a weak reference to your Controller object.
Since Greg and I have offered the same solution, here's an implementation of it you could use:
Usage would be for your controller to alloc/init the helper/proxy (or use the convenience method and retain it) and then in its -dealloc method call -invalidate followed by -release.
// .h file:
#import <Foundation/Foundation.h>
@interface GCTimerTarget : NSObject
{
@private
NSTimer* mTimerRef;
id mTrueTargetRef;
SEL mSelector;
}
@property (nonatomic, assign) NSTimer* timer;
@property (nonatomic, assign) id trueTarget;
@property (nonatomic, assign) SEL selector;
+ (GCTimerTarget*) scheduledTimerWithInterval:(NSTimeInterval) t target:(id) target selector:(SEL) selector repeats:(BOOL) repeats;
- (id) initForTarget:(id) trueTarget selector:(SEL) selector;
- (void) invalidate;
@end
/// .m file:
#import "GCTimerTarget.h"
@interface GCTimerTarget ()
- (void) timerCallback:(NSTimer*) timer;
@end
#pragma mark -
@implementation GCTimerTarget
@synthesize timer = mTimerRef;
@synthesize trueTarget = mTrueTargetRef;
@synthesize selector = mSelector;
+ (GCTimerTarget*) scheduledTimerWithInterval:(NSTimeInterval) t target:(id) target selector:(SEL) selector repeats:(BOOL) repeats
{
// convenience method makes the proxy and adds a scheduled timer to it. This can be used instead of the equivalent NSTimer class method
GCTimerTarget* tt = [[[self alloc] initForTarget:target selector:selector] autorelease];
tt.timer = [NSTimer scheduledTimerWithTimeInterval:t target:tt selector:@selector(timerCallback:) userInfo:nil repeats:repeats];
return tt;
}
- (id) initForTarget:(id) trueTarget selector:(SEL) selector
{
self = [super init];
if( self )
{
mTrueTargetRef = trueTarget;
mSelector = selector;
}
return self;
}
- (void) invalidate
{
self.trueTarget = nil;
[self.timer invalidate];
self.timer = nil;
// could call [self autorelease] here to make the proxy a one-line teardown, but it's probably safer to leave it as is
// and rely on a deliberate -release as usual.
}
- (void) timerCallback:(NSTimer*) timer
{
if([self.trueTarget respondsToSelector:self.selector])
[self.trueTarget performSelector:self.selector withObject:timer];
}
@end
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden