6

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

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

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

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

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

4

9 回答 9

6

只是这样它不会因未来的更新而中断

[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
}
于 2010-06-24T10:37:21.987 回答
2

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

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

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

   UIControlEventTouchDragInside     = 1 <<  2,
   UIControlEventTouchDragOutside    = 1 <<  3,
   UIControlEventTouchDragEnter      = 1 <<  4,
   UIControlEventTouchDragExit       = 1 <<  5,
于 2010-04-01T17:10:34.437 回答
1

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

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

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

希望能帮助到你!

于 2009-08-20T21:49:49.430 回答
1

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

    static UInt32 counter = 0;

counter++;

if((counter/2)*2 != counter) return;
于 2010-01-05T22:52:56.960 回答
1

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

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

// On down event
pressed = YES;

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

}

我希望它有所帮助。

哈密

于 2009-08-31T17:44:40.030 回答
0

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

static UInt32 counter = 0;

if ([[UIDevice currentDevice].systemVersion compare: @"4.2" options: NSNumericSearch] == NSOrderedAscending) {
    counter++;
    if((counter/2)*2 != counter) return;
}
于 2010-10-25T09:48:34.943 回答
0

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

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

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

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

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

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

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

于 2009-07-25T22:59:14.593 回答
0

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

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

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

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

于 2009-07-01T08:17:43.420 回答
-1

A simple solution, that won't break if Apple fix this ...feature (?) in the future is to add a property that stores the time since last interaction. and exit if it is an impossible short time since last interaction.

(in the code below, latestTimeMark, initially set to current time in 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;
于 2010-05-26T16:22:44.967 回答