UISlider returns two Touch Up Inside events, why is this happening?

I have a slider that I use to determine the float value. I am connecting a value changed to a method in my viewController. This part works great.

I need to know when the user starts touching the control, but not necessarily, every time the slider changes (I get events with a changed value for it). So I connected the Touch Up Inside event to another method in the viewController.

The problem is that this method is called twice when the user touches the UISlider control. WTF? This does not work with UIButtons or other touch events such as Touch Down.

I can get around this, I think, but it seems like a mistake in the way the slider knobs touch. Does anyone know why this is happening?

BTW : A double-touch event occurs even when Touch Up Inside is the only related event.

+6
iphone cocoa-touch uislider
source share
9 answers

Just so it doesn't break with future updates

[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 } 
+6
source share

if you want to subclass the slider, you can easily solve this by implementing endTrackingWithTouch and doing nothing:

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

the only caveat here is that some specific UIControlEvents will not fire properly. I believe that they are the following, but I did not conduct special testing to see which of them work and which do not. however, the touch has changed and touching inside certainly works without duplicate shooting.

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

I also had this problem, my solution was to add a logical "allowEvent". Then I hooked up UIControlEventTouchDown to a function that sets "allowEvent" to YES.

In the UIControlEventTouchUpInside selector, I checked if allowEvent, YES is allowed, then fire the event and set allowEvent to NO.

Then the event will be executed only once, even if it fires twice.

Hope this helps!

+1
source share

I think the easiest solution is to use the flag solution mentioned above.

I created a flag called (BOOL) pressed and added to the TouchUpInside and TouchDown events. So, you just need to check if the == YES function is pressed.

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

Hope this helps.

Hami

+1
source share

Thanks to everyone. I have the same problem. Here is some integer math that solves it for me:

  static UInt32 counter = 0; counter++; if((counter/2)*2 != counter) return; 
+1
source share

I just tried and I noticed the same behavior. It is called from two places, first from UISlider endTrackingWithTouch: withEvent: method (which is called by UIControl touchhesEnded: withEvent: method), and then from the same UIControl touchesEnded: withEvent: (which was first called by endTrakingWithTouch: withEvent :) ,.

In addition, when the touch ended outside the slider, the method is called only once by the endTrackingWithTouch: withEvent: method. The toucedEnded: withEvent: method calls this, but then does not call the callback, as it did when the touch ended inside the control.

Anyway, why are you connecting Touch Up Inside? Do you want to know when the user starts touching the control correctly? I think you should connect Touch Down instead of Touch Up Inside.

Edit: I see you need a changed value, and this changed value is called too often. I just repeated the test and noticed the following. The changed value is called between two touches of internal calls. Maybe you can do something about this?

0
source share

Since my previous comment was not well received, I decided to come up with a simple work for this problem if anyone is interested.

I know that this is not the most effective solution in the world, but it works the same way.

I created two methods: sliderUp and sliderChanged, related to TouchUp and ValueChanged, respectively. I also created a global variable int (timesFired if you do) so that it is initially set to zero

In the sliderUp method, I put any code that I have not missed twice. In my case, I remove the slider to the bottom if it is not at the top (for example, the slide function to unlock). I also reset timesFired returns to zero after a delay. to allow calling another method. just in case. (performSelector: withObject: afterDelay: if you don't know how to do this)

In the sliderChanged method, I first have an if statement: if (timesFired <1) {} (I also have an if statement to make sure my slider is maximum), and then include all the code that I want to execute only once, when the slider reaches its maximum value. to make sure this code runs only once, I also increase the time.

As soon as the user lifts his finger on timeFired, he will return to zero, and the whole process will begin again.

Now, as soon as I can figure out how to freeze the slider after they get to the top, I really will be pleased with this decision. (just turn it off?)

0
source share

This error has been fixed since 4.2. Now I am using Dan code as follows:

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

A simple solution that will not break if Apple fixes this ... function (?) In the future is to add a property that stores the time since the last interaction. and exit if it is not possible a short time after the last interaction.

(in the code below, lastTimeMark, the originally set 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; 
-one
source share

All Articles