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:25:01 +1000
On 19/04/2013, at 4:01 PM, Oleg Krupnov <email@hidden> wrote:
> recently encountered an alarming problem that I have never been
> aware of, and I'd like to ask about the best practice to handle it.
>
> Is it true that any object (let's call it Controller) that owns an
> NSTimer, scheduled to fire a method (let's call it -timerDidFire) of
> the same Controller, creates a circular reference and causes the
> Controller to never be released and the timer never stop triggering?
>
> It looks like scheduling the timer causes the run loop to retain a
> reference to the object that implements -timerDidFire, in this case
> it's the Controller. Is this true? Then this is a circular reference,
> right?
It depends on whether your controller retains the timer object. There is no reason for it to do so, since the run loop retains the timer and the timer retains its target (the controller).
There's a still a problem though, in that you need to invalidate the timer in order for the controller to be deallocated.
>
> In this case, if [_timer invalidate]; is called only in Controller's
> dealloc, then the timer never stops firing?
Yup.
>
> Which is the best way to prevent this problem? Currently I'm thinking
> about some kind of -[controller disconnect]; method that I need to
> call before [controller release]; in controller's parent object, but
> that seems a bit unwieldy solution.
You can always override release to stop the timer but this has the problem that whoever performs the first release stops the timer - that may not be who you expect. Having a distinct 'disconect' method is certainly a reasonable solution.
There are automatic solutions involving a private proxy object to be the timer's target that is owned by the controller. The controller can manage the proxy and timer in such a way that the controller can simply be dealloc'd and this in turn causes the proxy object to invalidate the timer, then releases the proxy. The proxy object is completely internal to your controller so no outside code needs to be aware of it.
There might be a better way, but adding an additional level of indirection to the timer's target in this way is a solution.
--Graham
_______________________________________________
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