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

Posted

技术标签:

【中文标题】UISlider 返回两个 Touch Up Inside 事件,为啥会这样?【英文标题】:UISlider returns two Touch Up Inside events, why does that happen?UISlider 返回两个 Touch Up Inside 事件,为什么会这样? 【发布时间】:2009-06-30 11:26:08 【问题描述】:

我有一个滑块,用于在某处设置浮点值。我将 Value Changed 连接到我的 viewController 中的一个方法。这部分工作正常。

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

问题在于,当用户触摸 UISlider 控件时,该方法会被调用两次。怎么回事?它不适用于 UIButtons 或其他触摸事件,如 Touch Down

我想我可以解决它,但这似乎是滑块控件处理触摸方式的错误。有人知道为什么会这样吗?

顺便说一句:即使 Touch Up Inside 是唯一连接的事件,也会发生双击事件。

【问题讨论】:

【参考方案1】:

只是为了不因未来的更新而中断

[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

【讨论】:

【参考方案2】:

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

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

这里唯一需要注意的是某些特定的 UIControlEvents 不会正确触发。我相信它们是以下几种,但我没有进行具体测试来查看哪些有效,哪些无效。但是触摸改变了,内部修饰肯定可以在没有重复触发的情况下工作。

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

【讨论】:

【参考方案3】:

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

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

那么事件即使触发两次也只会执行一次。

希望对你有帮助!

【讨论】:

【参考方案4】:

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

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

// On down event
pressed = YES;

// On up event
if (pressed)

  pressed = NO;
  // code here


希望对你有帮助。

哈密

【讨论】:

【参考方案5】:

谢谢大家。我有同样的问题。这里有一些整数数学可以帮我解决这个问题:

    static UInt32 counter = 0;

counter++;

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

【讨论】:

哎哟!这是什么意思?只有当数字是偶数时才返回?最好改用if (counter % 2 == 0) return; Apple 修复这个 bug 后会发生什么,这个解决方案不会弄乱你的应用程序吗?我强烈建议按照下面 bentech 的建议设置一个标志。【参考方案6】:

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

此外,当触摸在滑块之外结束时,endTrackingWithTouch:withEvent: 方法只会调用一次该方法。 touchesEnded:withEvent: 方法调用 this,但不会像在控件内触摸结束时那样调用回调。

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

编辑:我看到您需要更改的值,并且更改的值被频繁调用。我刚刚重新运行测试,并注意到以下内容。更改的值在两个内部调用之间调用。也许你可以用它做点什么?

【讨论】:

滑动完成后我需要做一些事情。 Touch Down 在滑动完成之前触发,Value Changed 在滑动发生时触发,这太频繁了。 我改变了我原来的答案:)【参考方案7】:

由于我之前的评论没有受到好评,我决定想出一个简单的解决方法来解决这个问题,以防有人感兴趣。

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

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

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

在 sliderChanged 方法中,我首先有一个 if 语句:if(timesFired

只要用户抬起手指,timeFired 就会被设置回零,整个过程可以重新开始。

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

【讨论】:

【参考方案8】:

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

static UInt32 counter = 0;

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

【讨论】:

啊!为什么除法和乘法只是为了区分奇数和偶数?使用模数! if (counter % 2 == 0) return;【参考方案9】:

一个简单的解决方案,如果 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;

【讨论】:

以上是关于UISlider 返回两个 Touch Up Inside 事件,为啥会这样?的主要内容,如果未能解决你的问题,请参考以下文章

同时使用 touch down 和 touch up 手势识别器

UIbutton 长按和 Touch Up 里面

第二个视图控制器中的 UIButton - Touch Up Inside 不起作用(Touch Down 可以)

UISlider 释放触摸时过于敏感

带有 Touch Up Inside 和 Touch Repeat 的 UIButton?

UIButton 子类忽略“Touch Up Inside”事件