问题无效&重新创建NSTimer(s)

时间:2010-02-02 22:04:26

标签: objective-c cocoa nstimer

我在开始时遇到问题&阻止NSTimers。文档说定时器由[timer invalidate];

停止

我有一个声明为这样的计时器对象

.h
NSTimer *incrementTimer;
@property (nonatomic, retain) NSTimer *incrementTimer;
.m
@synthesize incrementTimer;
-(void)dealloc {
 [incrementTimer release];
 [super dealloc];
 }

- 通常。

如果需要,我的方法会执行以下操作:

-(void)setGenCount {
    if(!condition1 && condition2) {
        incrementTimer = [NSTimer scheduledTimerWithTimeInterval: 2.0 
                                                      target: self 
                                                    selector:@selector(incrementBatteryVoltage:) 
                                                    userInfo: nil 
                                                     repeats: YES]; 
    }
}

以上所有内容都可以。但是,一旦该计时器完成它的工作,我希望它自己失效。我使计时器无效,因为有一个可以被调用的相等减量方法,如果它仍然是活动的,它将与incrementTimer作对。 (之前,我注意到我的两个计时器,如果活跃,通过增加和减少值(一种战斗)在同一个ivar上行动......没有崩溃)调用的选择器的工作方式如下:

-(void)incrementBatteryVoltage:(NSTimer *)timer {
    if(battVoltage < 24.0) {
         generatorDisplay.battVoltage += 0.1;
      }
    if(battery1Voltage == 24.0) {
         [timer invalidate];
      }
  }

我有一个减少电池数量的相同方法。 (前面提到过)
由于我的程序设计:界面模拟电压显示。当“机器”关闭时,无论电压值是多少,我都希望所有定时器都无效。我这样做是通过检查计时器是否有效来实现的。

-(void)deEnergizeDisplays {

   if([decrementTimer isValid]) {
        [decrementTimer invalidate];
        decrementTimer = nil;
     }

    if([incrementTimer isValid]) {
       [incrementTimer invalidate];
       incrementTimer = nil;
    }

我遇到了无数次“BAD_ACCESS”崩溃。错误的线路呼叫始终指向我的[timer isValid]呼叫。似乎如果计时器无效......指针 也不存在。我知道[timer invalidate]消息禁用了计时器,然后它从运行循环中删除然后它被释放。我的理解是:根据它的命名规则,它是一个自动释放的对象。

我的想法是:如果我发送保留消息,那么引用是否仍然存在?我尝试了几种组合,带走了:

timer = nil;

甚至代替:

if([timer isValid])

我试过了:

if([timer != nil])

和:

if(timer)

我总是遇到同样的崩溃。感谢您对启动和启动的任何帮助阻止NSTimers。

2 个答案:

答案 0 :(得分:9)

更新: 请参阅Darren's answer。问题是您在设置计时器时没有使用属性访问器。而不是:

incrementTimer = [NSTimer ...

你应该:

self.incrementTimer = [NSTimer ...

self.propertyName = ...语法将调用您的访问者方法,从而自动保留您发送给它的对象(因为您的属性设置为retain)。只需调用propertyName = ... 即可使用属性访问器。您只需直接更改ivar的值。


更新#2: 在与Peter Hosey进行了一次启发性的对话(见评论)之后,我删除了我之前的建议,即“永不保留或释放”您的计时器对象。我还完全重写了我之前的代码,因为我认为以下是更好的方法:

  

<强>或者Controller.h

NSTimer *voltageTimer;
float targetBatteryVoltage;
...
@property (nonatomic, retain) NSTimer *voltageTimer;
  

<强> Controller.m或者

@implementation Controller
@synthesize voltageTimer;

- (void)stopVoltageTimer {
    [voltageTimer invalidate];
    self.voltageTimer = nil;
}

- (void)setTargetBatteryVoltage:(float)target {
    [voltageTimer invalidate];
    targetBatteryVoltage = target;
    self.voltageTimer = [NSTimer scheduledTimerWithTimeInterval: 2.0
                                target: self
                              selector: @selector(updateBatteryVoltage:)
                              userInfo: nil
                               repeats: YES];
}

- (void)updateBatteryVoltage:(NSTimer *)timer {
    const float increment = 0.1;
    if (abs(battVoltage - targetBatteryVoltage) < increment) {
        [timer invalidate];
    }
    else if (battVoltage < targetBatteryVoltage) {
        generatorDisplay.battVoltage += increment;
    }
    else if (battVoltage > targetBatteryVoltage) {
        generatorDisplay.battVoltage -= increment;
    }
}

现在,您可以简单地设置目标电池电压,并且计时器魔术将在幕后发生:

[self setTargetBatteryVoltage:24.0];

您的断电方法如下:

- (void)deEnergizeDisplays {
    [self stopVoltageTimer];
}

答案 1 :(得分:3)

您需要retain incrementTimer中分配给setGenCount的值self.。您可以使用合成属性自动执行此操作,该属性可通过self.incrementTimer = [NSTimer scheduledTimerWithTimeInterval: ...

访问
{{1}}