iphone多个NSTimer故障
我对编程还是新手,所以如果这很愚蠢,请原谅。我正在编写一个简单的游戏,需要多个计时器以不同的时间间隔发送不同的消息,因此在创建游戏时,调用以下命令:iphone多个NSTimer故障,iphone,object,nstimer,Iphone,Object,Nstimer,我对编程还是新手,所以如果这很愚蠢,请原谅。我正在编写一个简单的游戏,需要多个计时器以不同的时间间隔发送不同的消息,因此在创建游戏时,调用以下命令: [self gameTimerValidate]; [self scoreTimerValidate]; - (void) gameTimerValidate { gameTimer = [NSTimer scheduledTimerWithTimeInterval:[myGame gIntervalSpeed] target:self sele
[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];
}
我在头文件(“NSTimer*gameTimer;”)中声明了scoreTimer和gameTimer。我在暂停游戏或完成关卡时使计时器失效,在继续游戏或进入下一关卡时再次调用上述方法
今天我花了几个小时试图弄明白为什么暂停游戏会使应用程序崩溃。在进行一些调试之后,我注意到gametimer的保留计数为0,而scoretimer的保留计数为2。当然,我不能使保留计数为0的计时器无效,但我不确定这是如何发生的
是否有一种特定的方法必须初始化两个不同的NSTimer?我在这上面搜索了几个小时都没有用…计时器不可重复使用。在使它们无效后,它们将从运行循环中删除,并且它们的保留计数将减少,从而导致它们在下次通过循环时取消分配。您必须创建新计时器或停止使其无效。计时器不可重复使用。在使它们无效后,它们将从运行循环中删除,并且它们的保留计数将减少,从而导致它们在下次通过循环时取消分配。您必须创建新的或停止使其无效。我认为您应该尝试找到您可能在哪里执行[scoreTimer retain],以及您可能在哪里多次使gameTimer无效(或释放)gameTimer(如果您检查了retainCount,并且是在您已使其无效一次之后,您只需要执行后者)。您不能通过调用以下任何一项来增加重新计数
[self gameTimerValidate];
[self scoreTimerValidate];
不止一次。您可能会泄漏内存,并且有两个计时器以相同的时间间隔触发,但您不会让其中一个计时器因此具有更高的重新计数
如果这两个实例变量是保留属性,并且您使用self.gameTimer=…,设置它们,那么我可以看到它们被额外保留了一段时间。但我看到的代码并不能解释你的问题
搜索这两个计时器的所有实例,看看还有什么可能会搞乱
一个建议是,您可能希望检查nil,如下所示:
- (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;
}
我认为你应该试着找出你可能在哪里做[scoreTimer retain],以及你可能在哪里多次使gameTimer失效(或释放)gameTimer(如果你在失效一次之后检查了retainCount,你只需要做后者)。您不能通过调用以下任何一项来增加重新计数
[self gameTimerValidate];
[self scoreTimerValidate];
不止一次。您可能会泄漏内存,并且有两个计时器以相同的时间间隔触发,但您不会让其中一个计时器因此具有更高的重新计数
如果这两个实例变量是保留属性,并且您使用self.gameTimer=…,设置它们,那么我可以看到它们被额外保留了一段时间。但我看到的代码并不能解释你的问题
搜索这两个计时器的所有实例,看看还有什么可能会搞乱
一个建议是,您可能希望检查nil,如下所示:
- (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;
}
NSTimer是一个棘手的类。它的行为不像你期望的那样 首先,计时器实例最终不是由初始化它们的对象保留的,而是由IIRC(nsrunlop)保留的。这意味着,如果您有一个创建计时器的对象,即使您销毁了创建它的对象以及自定义代码中的所有其他引用,计时器也将继续处于活动状态。计时器会不断地发出信息,而你却不知道这些信息是从哪里来的 其次,你不能停止/暂停并恢复计时器。当你宣布它无效时,它就死了 我建议创建一个轻量级的类来为您管理计时器,这样您就不必在代码的其余部分跟踪它。e、 g
@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];
}
NSTimer是一个棘手的类。它的行为不像你期望的那样 首先,计时器实例最终不是由初始化它们的对象保留的,而是由IIRC(nsrunlop)保留的。这意味着,如果您有一个创建计时器的对象,即使您销毁了创建它的对象以及自定义代码中的所有其他引用,计时器也将继续处于活动状态。计时器会不断地发出信息,而你却不知道这些信息是从哪里来的 其次,你不能停止/暂停并恢复计时器。当你宣布它无效时,它就死了 我建议创建一个轻量级的类来为您管理计时器,这样您就不必在代码的其余部分跟踪它。e、 g
@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];
}
感谢您的回复,在考虑之后,我将采用与TechZen所说的类似的方法,使用BOOL变量保持计时器运行,并使用该变量检查暂停等事件(即更改布尔值与停止和启动计时器)
(也是我第一次使用这个网站,还在学习答案的格式)再次感谢 感谢您的回复,在考虑之后,我将采用类似TechZen所说的方法,使用BOOL变量保持计时器运行,并使用该变量检查暂停等事件(即更改布尔值vs停止和启动计时器)
(也是我第一次使用这个网站,还在学习答案的格式)再次感谢 对于TechZen的light类,我认为您不应该释放上面的目标对象,因为您没有创建它(因此不拥有它)
}作为对TechZen的light类的回复,我认为您不应该释放上面的目标对象,因为您没有创建它(因此不拥有它) }