繁体   English   中英

UISlider返回两个Touch Up Inside事件,为什么会这样?

[英]UISlider returns two Touch Up Inside events, why does that happen?

我有一个滑块,我用它来设置某个浮动值。 我将Value Changed连接到viewController中的方法。 那部分工作正常。

我需要知道用户何时开始触摸控件但不一定是滑块更改的每一个瞬间(我收到了Value Changed事件)。 所以我将Touch Up Inside事件连接到viewController中的另一个方法。

问题是,当用户触摸UISlider控件时,该方法被调用两次。 WTF? 它与UIButton或其他触摸事件(如Touch Down)无关。

我认为,我可以解决它,但它似乎是滑块控件处理触摸的方式中的一个错误。 有人知道它为什么会发生吗?

BTW :即使Touch Up Inside是唯一连接的事件,也会发生双触摸事件。

正因如此,它不会打破未来的更新

[customSlider addTarget:self action:@selector(sliderDown:) forControlEvents:UIControlEventTouchDown];

[customSlider addTarget:self action:@selector(sliderAction:) forControlEvents:UIControlEventTouchUpInside];



- (void)sliderDown:(id)sender
{

    sliderused = NO;

}

- (void)sliderAction:(id)sender
{
    if(sliderused){
    return;
}

sliderused = YES;

//Your Code Here
}

如果你愿意对滑块进行子类化,你可以通过实现endTrackingWithTouch并且什么都不做来轻松解决这个问题:

- (void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{}

这里唯一需要注意的是,某些特定的UIControlEvents无法正常启动。 我相信他们是以下的,但我没有做具体的测试,看看哪些有效,哪些无效。 然而触摸变化和触摸内部肯定没有重复射击工作。

   UIControlEventTouchDragInside     = 1 <<  2,
   UIControlEventTouchDragOutside    = 1 <<  3,
   UIControlEventTouchDragEnter      = 1 <<  4,
   UIControlEventTouchDragExit       = 1 <<  5,

我也有这个问题,我的解决方案是添加一个布尔“allowEvent”。 然后我将UIControlEventTouchDown连接到一个将“allowEvent”设置为YES的函数。

在UIControlEventTouchUpInside的选择器中,我检查了allowEvent是否为YES,然后执行该事件并将allowEvent设置为NO。

然后,即使事件发生两次,事件也只会被执行一次。

希望能帮助到你!

我认为最简单的解决方案是使用上面提到的标志解决方案。

我创建了一个名为(BOOL)的标志,并将其添加到TouchUpInside和TouchDown事件中。 所以,你只需要检查是否按下==是。

// On down event
pressed = YES;

// On up event
if (pressed)
{
  pressed = NO;
  // code here

}

我希望它有所帮助。

哈密

谢谢你们。 我有同样的问题。 这是一些解决它的整数数学:

    static UInt32 counter = 0;

counter++;

if((counter/2)*2 != counter) return;

我刚试过,我注意到了同样的行为。 从两个地方调用它,首先来自UISlider的endTrackingWithTouch:withEvent:方法(由UIControl的touchesEnded:withEvent:方法调用),然后从相同的UIControl的touchesEnded:withEvent:方法(首先调用endTrakingWithTouch:withEvent:方法) 。

此外,当触摸在滑块外部结束时,该方法仅通过endTrackingWithTouch:withEvent:方法调用一次。 touchesEnded:withEvent:方法调用此方法,但之后不会调用回调,就像触摸在控件内部结束时一样。

无论如何,为什么要连接Touch Up Inside? 您想知道用户何时开始触摸控件权限? 我认为你应该连接Touch Down而不是Touch Up Inside。

编辑:我发现你需要更改的值,并且经常调用更改的值。 我只是重新进行测试,并注意到以下内容。 更改的值在两次内部调用之间调用。 也许你可以做点什么?

由于我以前的评论没有得到好评,所以我决定在有人感兴趣的情况下为这个问题提出一个简单的方法。

我知道它不是世界上最有效的解决方案,但它的工作原理是一样的。

我创建了两个方法:sliderUp和sliderChanged分别链接到TouchUp和ValueChanged。 我还创建了一个全局int变量(timesFired,如果你愿意)设置为初始设置为零

在sliderUp方法中,我放了任何我不介意触发两次的代码。 在我的情况下,如果它不在顶部,我会将滑块向下射到底部(就像滑动解锁功能一样)。 我也在延迟后将timesFired重置为零。 允许调用其他方法。 以防万一。 (performSelector:withObject:afterDelay:如果你不知道怎么做)

在sliderChanged方法中,我首先使用if语句:if(timesFired <1){}(我还有一个if语句以确保我的滑块最大)然后包含我想要只发生一次的所有代码,当滑块达到最大值时。 为了确保该代码只被触发一次,我也增加了timesFired。

一旦用户抬起他们的手指,时间就会被设置回零,整个过程可以重新开始。

现在,只要我知道如何在滑块到达顶部后冻结滑块,我就会对这个解决方案感到满意。 (会简单地禁用它吗?)

从4.2开始,此错误已得到修复。 我现在使用Dan的代码如下:

static UInt32 counter = 0;

if ([[UIDevice currentDevice].systemVersion compare: @"4.2" options: NSNumericSearch] == NSOrderedAscending) {
    counter++;
    if((counter/2)*2 != counter) return;
}

一个简单的解决方案,如果Apple在未来修复此功能(?),将不会破坏,即添加一个属性,用于存储自上次交互以来的时间。 并且如果自上次交互以来不可能短时间退出。

(在下面的代码中,latestTimeMark,最初在viewDidLoad中设置为当前时间)

NSDate *now = [NSDate date];
 double nowDouble = [now timeIntervalSince1970];
 double difference = nowDouble - self.latestTimeMark;
 self.latestTimeMark = nowDouble;
 //NSLog(@"difference is now: %f", difference);
 if(difference<0.01f) return;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM