我制作了一个带有计时器的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从它自己的选择器。
感谢。
答案 0 :(得分:13)
你没有进行运行循环,你已经安排了一个计时器在主运行循环上开始。
在运行循环中调度计时器之前,您应该将创建的NSTimer
对象存储为实例变量。
在updateCountdownLabel:
方法中,一旦满足结束条件,只需在计时器实例上调用-invalidate
即可。这将从运行循环中删除计时器,因为你从未保留它,它将被释放。
我已经更新了使用基于选择器的NSTimer
而不是基于NSInvocation
的方法。这意味着回调方法签名是按照您的期望定义的。它还避免了将NSTimer
对象存储在ivar中的需要:
- (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];
}
}