我制作了一个带有计时器的RunLoop,用于更新显示倒计时的标签。我需要RunLoop在倒计时达到零时停止,对于计时器正常完成的情况,我可以使用runUntilDate,日期是当前日期+倒计时的时间。问题是当用户在按钮完成之前取消倒计时时。我不知道如何告诉RunLoop从取消按钮动作停止。下面是RunLoop的代码:
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
[self methodSignatureForSelector:@selector(updateCountdownLabel:)]];
[invocation setTarget:self];
[invocation setSelector:@selector(updateCountdownLabel:)];
[[NSRunLoop mainRunLoop] addTimer:[NSTimer timerWithTimeInterval:1 invocation:invocation repeats:YES] forMode:NSRunLoopCommonModes];
方法只是告诉标签在每个循环中减少1。
我可以告诉取消按钮改变标签为零,并有运行循环选择器检查如果值为零,但RunLoop自己的选择器可以告诉它停止吗?
cancelPerformSelector:target:argument:
cancelPerformSelectorsWithTarget:
这些是我发现的最接近的,但它们似乎不能从RunLoops自己的选择器内部工作,或者至少没有以任何方式我尝试过它们。
基本上我需要让按钮告诉RunLoop停止,或者以某种方式从它自己的选择器停止RunLoop。
谢谢。
您没有创建一个运行循环,您已经在主运行循环上安排了一个计时器。
您应该做的是在调度运行循环的计时器之前将创建的NSTimer
对象存储为实例变量。
在你的updateCountdownLabel:
方法中,一旦你的结束条件已经满足,就在你的计时器实例上调用-invalidate
。这将从运行循环中删除计时器,并且由于您从未保留它,因此它将被释放。
我已经更新了方法,使用基于选择器的NSTimer
而不是基于NSInvocation
的方法。这意味着回调方法签名是按您期望的方式定义的。它还避免了在ivar:
NSTimer
对象的需要。- (void)startCountDown
{
NSTimer* timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateCountdownLabel:) userInfo:nil repeats:YES]
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
- (void)updateCountdownLabel:(NSTImer*)timer
{
if(thingsAreAllDone)
{
[timer invalidate];
}
}