无法取消执行块的NSTimer

时间:2013-06-04 15:02:28

标签: ios objective-c button timer nstimer

我知道这些NSTimer问题已多次出现,但由于似乎没有涉及执行更改UI的块,我认为这仍然是一个原始问题。

我有一个UIButton的子类,为方便起见(我来自Android背景),它有一个onClickonHoldClick函数。 onClick只需一个块并在响应UIControlEventTouchUpInside的选择器中执行它。点击功能很棒。例如:

[myButton setOnClick:^{
    NSLog(@"clicked");
}];

暂停点击功能效果不佳。

[myButton setOnHoldClick:^{
    NSLog(@"still holding click...");
}];

这会侦听UIControlEventTouchDown事件,并在延迟后执行任务:

- (void)clickDown:(id)sender
{
    isClicked = YES;

    [self performSelector:@selector(holdLoop:) withObject:nil afterDelay:delay];//For the sake of the example, delay is set to 0.5  
}

保持循环在另一个函数上运行重复计时器,该函数处理块执行( timer 变量是头文件中声明的NSTimer):

-(void)holdLoop:(id)sender
{
    [self cancelTimers];
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(death:) userInfo:nil repeats:YES];
}

-(void)death:(id)_delay
{

    if (isClicked)
    {
        _holdBlock();
    }
    else
    {
        [self cancelTimers];

    }
}

执行的块会更改float的值,该值用于更新标签的值,然后重新绘制。

第一次发生暂停点击事件时,效果很好。在那之后,似乎定时器没有被取消,并且仍然添加了新的定时器。这就是我的cancelTimers函数的样子(这里的调用是从关于这个主题的其他问题的集合中检索的):

-(void)cancelTimers
{
    [_timer invalidate];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(death:) object:nil];
}

我做错了什么,我该如何解决?

修改

事实上,我确实已经有了响应内部修饰的功能:

- (void)clickUp:(id)sender
{
    isClicked = NO;
    [self cancelTimers];
    _clickBlock();
}

此外,我意识到问题来自未处理的取消事件。 iOS有什么原因可以自动取消长按吗?

2 个答案:

答案 0 :(得分:2)

<强>解决

由于该块重新绘制了UI,因此它还重新绘制了按钮(并重置了它们的功能)。此事件导致在按钮上调用取消事件 - 未处理。添加以下内容:

[self addTarget:self action:@selector(cancelClick:) forControlEvents:UIControlEventTouchCancel];
[self addTarget:self action:@selector(cancelClick:) forControlEvents:UIControlEventTouchUpOutside];


-(void)cancelClick:(id)sender
{
    isClicked = NO;
    [self cancelTimers];
}

除了重新考虑块中所做的更改之外,还让我解决了这个问题。

答案 1 :(得分:1)

正如我从评论和代码中所理解的那样,clickDown:UIControlEventTouchDown调用,因此当第一次按下按钮时isClicked被设置为YES 。您需要为事件UIControlEventTouchUpInside添加选择器。当用户在按钮的边界处抬起他的手指时,它会被呼叫。在该方法中,将isClicked设置为NO