NSTimer 错误访问

Posted

技术标签:

【中文标题】NSTimer 错误访问【英文标题】:NSTimer bad access 【发布时间】:2011-02-17 06:24:31 【问题描述】:

我正在尝试创建一个 NSTimer,然后使其无效并释放它,然后将其设置为一个新的计时器。但是,在尝试再次设置计时器成员 var 时,我得到了 EXC_BAD_ACCESS。

代码如下:

1)我设置了定时器成员变量(设置为保留)

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

2) 我放手了

    [mPageTimer invalidate];
    [mPageTimer release];

当我再次尝试在步骤 1 中调用 sn-p 时,这会导致崩溃,但我不知道为什么。我通过设置保留它,然后释放它,所以不应该照顾对象并且我的成员 var ok 设置为新分配的计时器吗?

如果我这样做,它不会崩溃并且可以正常工作:

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

我看不出我在释放对象时做错了什么,因为不管是不是这种情况,我不应该总是将我的成员 var 设置为任何新创建的 nstimer、泄漏或不是吗?

【问题讨论】:

检查代码中的任何其他地方,您将在 release 之后将消息传递给 mPageTimer。因为您可以将消息传递给nil,所以它可能不会崩溃。 【参考方案1】:

可以安全地假设...

    sn-p 2) 不是来自@property的setter,而是来自另一个方法你 只需@synthesize mPageTimer 定时器的声明是@property (nonatomic, retain) NSTimer* mPageTimer? (无论是非原子的还是原子的都无关紧要)

如果是这种情况,您的崩溃是意料之中的:

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!

简而言之:如果您有一个计时器属性,提供您自己的设置器并让每个访问都使用它。 (允许两个例外:1. setter 的实现 2. 在你 release timer* 的 dealloc 中)

(* 不要使你在 dealloc 中成为目标的计时器无效:It is absolutely pointless!)

【讨论】:

您对上述 3 个假设是正确的。通过阅读您的帖子和链接,我可以收集到吗,因为 runloop 保留了我的计时器,而不是编写 setter,我可以将其声明为分配而不是保留,然后使用调用无效作为中断/关闭的手段-在它触发之前关闭一个计时器?这意味着我会使用 scheduleTimerWithTimeInterval 创建它,而不需要调用 release,对吗? 德语单词“Jein”需要有英文翻译!是的,没有必要保留计时器,因为运行循环已经这样做了。不,如果您决定通过@property 存储计时器,我敦促您提供自己的设置器(无论该属性是分配还是保留)。也就是说:如果您真的需要保留对计时器的引用以取消它,请确保在执行pageTimerCallback 返回后,您对计时器的引用是nil

以上是关于NSTimer 错误访问的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSTimer 的秒表错误地在显示中包含暂停时间

错误无法下标“AnyObject?”类型的值在 NSTimer 的 userInfo 中使用数组

当 runloop 被阻塞时,NSTimer 不会触发

如何用另一个 NSTimer 停止 NSTimer?

使用 NSTimer 时发送到实例的无法识别的选择器

iOS 中的 NSTimer