2009-10-18 83 views
1

我还是新编程,所以如果这很愚蠢,请原谅我。我编写一个简单的游戏,需要多个计时器,以不同的时间间隔发送不同的信息,所以在创建游戏时,以下称为:iphone多NSTimer的麻烦

[self gameTimerValidate]; 
[self scoreTimerValidate]; 

- (void) gameTimerValidate 
{ 
gameTimer = [NSTimer scheduledTimerWithTimeInterval:[myGame gIntervalSpeed] target:self selector:@selector(gameTimerInterval:) userInfo:nil repeats:YES]; 
} 

- (void) scoreTimerValidate 
{ 
scoreTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(scoreTimerInterval:) userInfo:nil repeats:YES]; 
} 

我已在scoreTimer和gameTimer在我的头文件中声明(” NSTimer * gameTimer;“)。当暂停游戏或完成关卡时,我会使计时器失效,并分别在恢复游戏或进入下一关时再次调用上述方法。

我今天花了数小时试图弄清为什么暂停游戏会导致应用程序崩溃。在做了一些调试之后,我发现gametimer的保留数是0,scoretimer是2。当然,我不能使保留数为0的定时器无效,但我不确定这是怎么产生的。

有什么特定的方法我必须初始化两个不同的NStimers?我一直在这个小时寻找无济于事...

回答

2

定时器不可重复使用。在使它们无效后,它们将从运行循环中移除,并且它们的保留计数会减少,从而导致下一次通过循环释放它们。您将不得不创建新的或停止使其失效。

0

我认为你应该尝试找出你可能在做什么[scoreTimer retain],以及你可能会多次失效(或释放)gameTimer的地方(你只需要做后者,如果你在哪里检查过retainCount,是在你失效一次之后)。您不能通过致电

[self gameTimerValidate]; 
[self scoreTimerValidate]; 

不止一次增加保留计数。你会泄漏内存,并且有两个定时器以相同的时间间隔触发,但是你不会让这些定时器中的一个有更高的retainCount,因为这样。

如果这两个实例变量是保留属性,并且您使用self.gameTimer = ...设置它们,那么我可以看到它们保留了额外的时间。但是我看到的代码并不能解释你的问题。

搜索这两个计时器的所有实例,看看还有什么可能会弄乱事情。

一个建议,你可能要检查为零,这样的:

- (void) gameTimerValidate 
{ 
    if (gameTimer == nil) 
     gameTimer = [NSTimer scheduledTimerWithTimeInterval:[myGame gIntervalSpeed] target:self selector:@selector(gameTimerInterval:) userInfo:nil repeats:YES]; 
} 

- (void) scoreTimerValidate 
{ 
    if (scoreTimer == nil) 
     scoreTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(scoreTimerInterval:) userInfo:nil repeats:YES]; 
} 
- (void) invalidateMyTimers { 
    [gameTimer invalidate], gameTimer = nil; 
    [scoreTimer invalidate], scoreTimer = nil; 
} 
3

的NSTimer是一个棘手的类。它的行为不像你期望的那样。

首先,定时器实例最终不会由初始化它们的对象保留,而是由IIRC(NSRunLoop)保存。这意味着如果您有一个创建计时器的对象,即使您销毁创建它的对象以及您的自定义代码中的所有其他引用,该计时器仍将保持活动状态。计时器将继续沿着消息发射,你不知道它们来自哪里。

其次,你不能停止/暂停和恢复计时器。当你无效时,它已经死了。

我建议创建一个轻量级类来管理你的计时器,这样你就不必在代码的其余部分跟踪它。例如

@interface SDL_SimpleTimerController : NSObject { 
    NSTimer *currentTimer; 
    NSTimeInterval theInterval; 
    id theTargetObj; 
    SEL theSelector; 

    BOOL timerIsRunning; 
} 
@property (nonatomic,retain) NSTimer *currentTimer; 
@property NSTimeInterval theInterval; 
@property (nonatomic,retain) id theTargetObj; 
@property SEL theSelector; 
@property BOOL timerIsRunning; 

-(SDL_SimpleTimerController *) initWithInterval:(NSTimeInterval)anInterval forTarget:(id)aTargetObj andSelector:(SEL)aSelector; 

-(void) startTimer; 
-(void) stopTimer;         
@end 

@implementation SDL_SimpleTimerController 
@synthesize currentTimer; 
@synthesize theInterval; 
@synthesize theTargetObj; 
@synthesize theSelector; 
@synthesize timerIsRunning; 

-(SDL_SimpleTimerController *) initWithInterval:(NSTimeInterval) anInterval forTarget:(id) aTargetObj andSelector:(SEL) aSelector 
{ 
    self=[super init]; 
    theInterval=anInterval; 
    theTargetObj=aTargetObj; 
    theSelector=aSelector; 
    timerIsRunning=NO; 

    return self; 

}// end initWithInterval: 


-(void) startTimer{ 
    if (currentTimer) { 
     currentTimer=Nil; 
    } 
    currentTimer=[NSTimer scheduledTimerWithTimeInterval:theInterval target:theTargetObj selector:theSelector userInfo:Nil repeats:YES]; 
    timerIsRunning=YES; 
}//end startTimer 

-(void) stopTimer{ 
    if (currentTimer) { 
     [currentTimer invalidate]; 
     currentTimer=Nil; 
    } 
    timerIsRunning=NO; 
}// end stopTimer 

- (void)dealloc { 
    if (currentTimer) { 
     [currentTimer release]; 
     currentTimer=Nil; 
    } 
    [theTargetObj release]; 
    theTargetObj=Nil; 
    [super dealloc]; 
} 
0

感谢您的答复,给它经过一番思考,我要去跟类似于TechZen说的方法,并与只保留定时器与一个布尔变量运行,并使用该变量检查事件如暂停等(即改变布尔与停止和启动计时器)。

(也是我第一次使用本网站,仍在学习答案的格式)再次感谢!

0

在回答TechZen的光类,我想你不应该释放上面你没有创建它的目标对象(因此不拥有它)

(void)dealloc { 
if (currentTimer) { 
    [currentTimer release]; 
    currentTimer=Nil; 
} 
**[theTargetObj release];** 
theTargetObj=Nil; 
[super dealloc]; 

}