Circular release problem with NSTimer...

Discussion in 'iOS Programming' started by ArtOfWarfare, Jun 11, 2012.

  1. ArtOfWarfare, Jun 11, 2012
    Last edited: Jun 11, 2012

    ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #1
    I have an object that, in its init method, sets up an ivar with an NSTimer. The object itself is the target for the timer, which causes the object to get a +1 to its retain count.

    It seems to me that to balance setting up the timer, I need to tell the timer to invalidate and release. Since it was created in init, the balance belongs in dealloc, correct?

    But this causes an issue:
    - The object has been +1'd by the timer.
    - Thus the object won't get its corresponding -1 until the timer is invalidated.
    - The timer won't be invalidated until the object's retainCount hits zero.
    - The retainCount won't hit zero until the timer is invalidated.

    So it seems like there are two possibilities, neither of which is any good:
    1 - I could call autorelease on the object right after the timer is created. But then it would be over released when the timer is told to invalidate in the dealloc method, would it not?
    2 - I can ignore the issue and the program will appear to work, except there will be a memory leak.

    Edit: I attempted to do #1. I get this message when the object is dealloced.
    Code:
    *** -[CFRunLoopTimer release]: message sent to deallocated instance 0x105d0cd70
    I tried adding in a [self retain] to the dealloc method, but that didn't change anything (not that I really expected it to. Even if it worked, I wouldn't have considered it an acceptable solution.)

    Edit 2X: Actually... I might be misreading the issue... it seems that the issue is that when I set up the timer, I didn't retain it. Instead, it's just a scheduled timer which adds it to the run loop, which retains it. When I call invalidate, that causes it to remove it from the run loop, which releases it. So releasing the timer after invalidating it is causing the over-release issue.
     
  2. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #2
    Whether you need release or not depends on which method you are calling to schedule the timer. Read the Timer Programming Topics guide. It will give you examples of how to keep track of timers in your class. There's even a section called "Memory Management" that will help guide you. But really what it comes down to is if you use the 'scheduleTimer...' methods, then you can call 'invalidate' later, set your iVar to nil, and you don't have to worry about releasing the timer.
     
  3. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #3
    First rule of timers: when you invalidate a timer you set its ivar to nil. Anything different leads to madness.

    Typically there is some event that indicates that the timer should be invalidated. Things like: user hits back button, network request returns, user hits pause or stop button, etc. Use those events to invalidate your timer. Then the view controller won't be retained anymore and the retain-cycle is broken.
     
  4. Ides macrumors member

    Joined:
    Mar 27, 2012
    #4
    Timer

    If you set up the timer to not repeat itself, then as soon as it fires it will be invalidated and removed from the run loop, and will release your object on its own. You don't need to call release or invalidate on it.
     

Share This Page