NSTimer bad access

痞子三分冷 提交于 2019-12-11 09:00:46

问题


I'm trying to create an NSTimer, then invalidate and release it, then set it to a new timer. However, I am getting an EXC_BAD_ACCESS when trying to set the timer member var again.

Code below:

1) I set the timer member var (it's set to retain)

self.mPageTimer = [NSTimer scheduledTimerWithTimeInterval:kPageTimerInterval target:self selector:@selector(pageTimerCallback) userInfo:nil repeats:NO];

2) I let it go

    [mPageTimer invalidate];
    [mPageTimer release];

This results in the crash when I try to call the snippet in step 1 again, but I am not sure why. I retained it by setting it, and then I release it, so shouldn't the object be taken care of and my member var ok to set to a new allocated timer?

If I do this, it doesn't crash and works fine:

    [mPageTimer invalidate];
    [mPageTimer release];
    mPageTimer = nil;

I can't see how I'm doing something wrong with releasing the object, because, regardless of if that were the case, shouldn't I be able to always set my member var to whatever newly created nstimer, leak or not?


回答1:


Is it safe to assume, that...

  1. snippet 2) is not from the setter of the @property, but from another method while you
  2. simply @synthesize mPageTimer and
  3. the declaration for the timer is @property (nonatomic, retain) NSTimer* mPageTimer?
    (whether nonatomic or atomic doesn't matter)

If that's the case, your crash is expected:

create timer (timer retains you, timer is autoreleased!)
schedule timer (runloop retains the timer)
assignment through setter (you retain the timer)
... (time passes)
has it fired?
Yes:
    since your timer is non-recurring, the runloop has marked it
    as invalid and released it after invocation of "pageTimerCallback:"
calling "invalidate":
    has it fired?
    No:
        runloop unschedules and releases
    Yes:
        noop or release (read: "I don't know and admittedly don't care")
calling "release" (you are no longer the owner)
... (time passes)
assignment through synthesized setter:
    [newTimer retain];
    [oldTimer release]; // Crash due to overrelease!

So in short:
If you have a property for a timer, provide your own setter and make every access use it.
(Two exceptions allowed: 1. implementation of the setter 2. in dealloc where you release the timer*)

(* Don't invalidate a timer that you're the target of in dealloc: It is absolutely pointless!)



来源:https://stackoverflow.com/questions/5025722/nstimer-bad-access

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!