我知道这些NSTimer
问题已多次出现,但由于似乎没有涉及执行更改UI的块,我认为这仍然是一个原始问题。
我有一个UIButton
的子类,为方便起见(我来自Android
背景),它有一个onClick
和onHoldClick
函数。 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有什么原因可以自动取消长按吗?
答案 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
。