我知道这些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
}
保持循环在另一个函数上运行一个重复的计时器,该函数处理块执行(计时器变量是头文件中声明的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];
}
}
执行块修改浮点数的值,该浮点数用于更新标签的值,然后重新绘制标签的值。
第一次hold click事件发生时,这种方法非常有效。在那之后,计时器似乎不会被取消,新的计时器仍然会被添加。这是我的cancelTimers
函数的样子(这里的调用是从关于这个主题的其他问题的集合中检索的):
-(void)cancelTimers
{
[_timer invalidate];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(death:) object:nil];
}
我做错了什么,我如何修复它?
编辑
事实上,我已经有了响应触摸的函数:
- (void)clickUp:(id)sender
{
isClicked = NO;
[self cancelTimers];
_clickBlock();
}
此外,我已经意识到这个问题来自一个未处理的取消事件。iOS会自动取消我的长按吗?
已解决
由于块重绘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];
}
以及重新考虑在块中所做的更改,使我度过了这个问题。
正如我从注释和代码中理解的那样,clickDown:
是为UIControlEventTouchDown
调用的,所以当按钮第一次被触摸时,isClicked
被设置为YES
。您需要向事件UIControlEventTouchUpInside
添加一个选择器。当用户在按钮的边界内抬起手指时,它就会被调用。在该方法中,设置isClicked
为NO
。