sam*_*u_1 3 cocoa objective-c nstimer
我在启动和停止NSTimers时遇到了问题.文档说[计时器无效]停止计时器;
我有一个声明为这样的计时器对象
.h
NSTimer *incrementTimer;
@property (nonatomic, retain) NSTimer *incrementTimer;
.m
@synthesize incrementTimer;
-(void)dealloc {
[incrementTimer release];
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
-通常.
如果需要,我的方法执行以下操作:
-(void)setGenCount {
if(!condition1 && condition2) {
incrementTimer = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(incrementBatteryVoltage:)
userInfo: nil
repeats: YES];
}
}
Run Code Online (Sandbox Code Playgroud)
上面的一切都很好.但是,一旦该计时器完成它的工作,我希望它自己失效.我使计时器无效,因为有一个可以被调用的相等减量方法,如果它仍然是活动的,它将与incrementTimer作对.(之前,我注意到我的两个计时器,如果活跃,通过增加和减少值(一种战斗)在同一个ivar上行动......没有崩溃)调用的选择器如下工作:
-(void)incrementBatteryVoltage:(NSTimer *)timer {
if(battVoltage < 24.0) {
generatorDisplay.battVoltage += 0.1;
}
if(battery1Voltage == 24.0) {
[timer invalidate];
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个减少电池数量的相同方法.(前面提到过)
由于我的程序设计:界面模拟电压显示.当"机器"关闭时,无论电压值是多少,我都希望所有定时器都无效.我这样做是通过检查计时器是否有效来完成的.
-(void)deEnergizeDisplays {
if([decrementTimer isValid]) {
[decrementTimer invalidate];
decrementTimer = nil;
}
if([incrementTimer isValid]) {
[incrementTimer invalidate];
incrementTimer = nil;
}
Run Code Online (Sandbox Code Playgroud)
我收到了很多"BAD_ACCESS"崩溃.错误的线路呼叫始终指向我的[timer isValid]呼叫.似乎如果定时器无效......指针也不存在.我知道[timer invalidate]消息禁用了计时器,然后它从运行循环中删除然后它被释放.我的理解是:根据它的命名规则,它是一个自动释放的对象.
我的想法是:如果我发送保留消息,那么引用是否仍然存在?我尝试了几种组合,带走了:
timer = nil;
Run Code Online (Sandbox Code Playgroud)
甚至代替:
if([timer isValid])
Run Code Online (Sandbox Code Playgroud)
我试过了 :
if([timer != nil])
Run Code Online (Sandbox Code Playgroud)
和:
if(timer)
Run Code Online (Sandbox Code Playgroud)
我总是得到同样的崩溃.感谢您对启动和停止NSTimers的任何帮助.
更新:见 Darren的回答.问题是您在设置计时器时没有使用属性访问器.代替:
incrementTimer = [NSTimer ...
Run Code Online (Sandbox Code Playgroud)
你应该有:
self.incrementTimer = [NSTimer ...
Run Code Online (Sandbox Code Playgroud)
该self.propertyName = ...语法会打电话给你的访问方法,从而自动保留您发送给它(因为你的属性被设置为对象retain).简单地调用propertyName = ...并没有使用属性访问器.您只需直接更改ivar的值即可.
更新#2:在与Peter Hosey进行了一次启发性的对话(见评论)之后,我已经删除了我之前的建议,即"永不保留或释放"您的计时器对象.我还完全重写了我之前的代码,因为我认为以下是更好的方法:
Controller.h:
NSTimer *voltageTimer;
float targetBatteryVoltage;
...
@property (nonatomic, retain) NSTimer *voltageTimer;
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以简单地设置目标电池电压,并且计时器魔术将在幕后发生:
[self setTargetBatteryVoltage:24.0];
Run Code Online (Sandbox Code Playgroud)
您的断电方法如下:
- (void)deEnergizeDisplays {
[self stopVoltageTimer];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4685 次 |
| 最近记录: |