• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Circular references caused by scheduled NSTimers?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Circular references caused by scheduled NSTimers?


  • Subject: Re: Circular references caused by scheduled NSTimers?
  • From: Oleg Krupnov <email@hidden>
  • Date: Fri, 19 Apr 2013 11:07:25 +0300

Thanks for your answers!

Now I'm thinking that I'd rather create a helper category on NSTimer
with a method that will schedule a timer but under the hood also
create the helper object. In this way, the current code of my project
will almost not change (only change the scheduling method). The helper
class will be private. The helper will not be retained by anyone
except the run loop and will be dealloced immediately after the timer
is invalidated

@interface TimerHelper
@property (nonatomic, assign) id target;
@property (nonatomic, assign) SEL action;
- (void)timerDidFire;
@end

@implementation TimerHelper
- (void)timerDidFire
{
  [_target performSelector:_action withObject:nil];
}
@end

@implementation NSTimer (Helper)

+ (NSTimer*)scheduleTimerWithInterval:(NSTimeInterval)interval
target:(id)target action:(SEL)action
{
   TimerHelper* helper = [[[TimerHelper alloc] init] autorelease];
   helper.target = target;
   helper.action = action;
    NSTimer* timer =  [NSTimer scheduledTimerWithTimeInterval:interval
target:helper selector:@selector(timerDidFire) userInfo:nil
repeats:YES];
   return timer;
}

@end

@implementation Controller
{
   NSTimer* _timer;
}

- (void)someMethod
{
  _timer = [[NSTimer scheduleTimerWithInterval:interval target:self
action:@selector(someTimerDidFire)] retain];
}

- (void)dealloc
{
   [_timer invalidate];
   [_timer release];
   [super dealloc];
}

@end

I think this is a more elegant solution than public helper. Any caveats?

On Fri, Apr 19, 2013 at 9:53 AM, Graham Cox <email@hidden> wrote:
>
> 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

References: 
 >Circular references caused by scheduled NSTimers? (From: Oleg Krupnov <email@hidden>)
 >Re: Circular references caused by scheduled NSTimers? (From: Greg Parker <email@hidden>)
 >Re: Circular references caused by scheduled NSTimers? (From: Graham Cox <email@hidden>)

  • Prev by Date: Re: NSScrollView in NSTabView autolayout problem
  • Next by Date: Showing a drawer on a sheet
  • Previous by thread: Re: Circular references caused by scheduled NSTimers?
  • Next by thread: Re: Circular references caused by scheduled NSTimers?
  • Index(es):
    • Date
    • Thread