我在开始时遇到问题&阻止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。
答案 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}}