以下是我的代码:

.h文件:

#import "Foundation/Foundation.h"
@interface GObject:NSObject{
    NSTimer* m_Timer;
}
@property(nonatomic, retain) NSTimer* m_Timer;

- (void)Initialize;
- (void)TimerCallback:(NSTimer*)pTimer;
@end

.m文件:
@implementation GObject

@synthesize m_Timer

- (void) Initialize{
    self.m_Timer = [NSTimer scheduledTimerWithTimeInterval:5.0
                       target:self
                       selector: @selector(TimerCallback:)
                       userInfo: nil
                       repeats: YES];

}

- (void)TimerCallback:(NSTimer*)pTimer {
    //Some Code
}
- (void)dealloc {
    [m_Timer invalidate]; //--Crashes Here
    [m_Timer release];
    m_Timer = nil;
    [super dealloc];
}
@end

现在,当调用dealloc时,程序在使计时器无效的行中崩溃。接下来的两行甚至都不会被调用。我收到“EXC_BAD_ACCESS”错误。谁能告诉我为什么可能会发生这种情况,以及在类中停止和释放NSTimer成员变量的正确方法是什么?

最佳答案

我做了一些研究和测试,并且可以找出我自己问题的答案。好的,它开始了:

每当我们将self分配为NSTimer的目标时,计时器就会保留对我们对象的引用。如果计时器正在重复(或具有较长的时间段),则它不会自行失效(或者如果不重复,它将花费太长的时间自动失效)。因此,即使对象同时释放,它也不会调用dealloc方法,因为保留计数至少为1。现在,我强行尝试通过调用对象的重复释放来释放对象,直到保留为止计数变为0。那是我的错误。

但是,如果不这样做,您的对象将保持事件状态,并且最终会因各种发行版本丢失对该对象的其余引用而导致内存泄漏。唯一保留的将是NSTimer。这听起来像是一个僵局。我的代码崩溃了,因为当delloc试图使NSTimer无效时,它试图释放它持有的引用。但是由于我以前是个聪明人,并且已经将保留计数减少到0,所以这将导致内存异常。

为了解决这个问题,首先我清理了行为并删除了代码以强制释放该对象。然后,在我想要分配对象之前,我调用了NSTimer的invalidate函数。这释放了Timer拥有的目标实例。之后,在我的对象上调用release成功分配了它。

最重要的是,如果您的对象具有重复或不自动失效(跳过)的NSTimers,则切勿在delloc函数中使它们失效。在计时器将实例保存到您的对象之前,不会调用delloc。在释放对象之前,应具有清除功能以使计时器无效。这就是我想出的解决方案。如果有更好的解决方案,我当然很想知道。

10-08 08:06
查看更多