Re: NSTimer memory management
Re: NSTimer memory management
- Subject: Re: NSTimer memory management
- From: Jeff Johnson <email@hidden>
- Date: Wed, 22 Sep 2010 20:50:34 -0500
It might be informative to see the entire backtrace and/or the entire source for the class, but in any case, I believe that the issue is "target:self". According to the NSTimer documentation, "The target object is retained by the timer and released when the timer is invalidated."
Your object retains the timer, and the timer retains your object. That is obviously a kind of retain cycle. What can happen is that your app gets into a situation where the only thing that retains a reference to your object is its own theTimer ivar. When the timer is invalidated, it releases your object (the target), and at that point it has a 0 retainCount, so your object is immediately deallocated. Then, boom!
The NSTimer API is somewhat unfortunate. It would probably be better to have a delegate API where the delegate is not retained. However, that ship has sailed. What you need to do is avoid the retain cycle. What I sometimes do is to create a private timer target that posts an NSNotification when the timer fires, and then your owning object with theTimer ivar is added as an observer of the notification. Your object is the owner of both the timer and the timer target, but there is no retain cycle.
-Jeff
On Sep 22, 2010, at 6:38 PM, email@hidden wrote:
> Hi,
>
> Is this an over-release?
>
> timer = [ [NSTimer scheduledTimerWithTimeInterval: ...] retain];
> ...
> [timer invalidate];
> [timer release];
>
> I've seen this pattern so many times I figured it was correct,
> although it doesn't seem to comply with the memory management rules
> (i. e. the timer is first implicitly released when invalidated, then
> explicitly released again).This never caused a problem on my Intel,
> but now I got several crash reports indicating an over-release on X86:
>
> Thread 0 Crashed: Dispatch queue: com.apple.main-thread
> 0 com.apple.CoreFoundation 0x92752c94 CFRelease + 196
> 1 com.apple.CoreFoundation 0x927c97c1 __CFRunLoopTimerDeallocate + 33
> 2 com.apple.CoreFoundation 0x92752e31 _CFRelease + 353
> 3 myApp 0x0000878a 0x1000 + 30602 // =
> invalidateTimer method
>
> Can someone please help clarify? This is my full code:
>
> - (void)invalidateTimer
> {
> if ( [theTimer isValid] ) {
> [theTimer invalidate];
> [theTimer release]; // crashes here
> theTimer = nil;
> }
> }
>
> - (void)startTimer
> {
> [self invalidateTimer];
> theTimer = [[NSTimer scheduledTimerWithTimeInterval:300 target:self
> selector:@selector(timerFireMethod:) userInfo:nil repeats:NO] retain];
> }
_______________________________________________
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