2

I have some UIButton instances that execute different code on their UIControlEventTouchDown and UIControlEventTouchUpInside events. At the moment I'm hitting an issue where if the user touched down, then dragged their finger out of the UIButton's bounds before touching up, the TouchUpInside code isn't run, and as such, the next TouchDown causes a crash.

I need a way to error-proof this, so that after a TouchDown, the TouchUpInside code is executed if the finger is: a) lifted over the button, b) dragged off the button, or c) cancelled in some other way.

a) is solved by UIControlEventTouchUpInside, and I've tried both UIControlEventTouchDragExit and UIControlEventTouchUpOutside, but I can't get situations b) or c) solved.

Any idea how I can handle this? Here's my code:

[newBall.button addTarget: self action: @selector(buttonDown:) forControlEvents: UIControlEventTouchDown];
[newBall.button addTarget: self action: @selector(buttonUp:) forControlEvents: UIControlEventTouchUpInside];

- (void) buttonDown: (id) sender
{
    NSLog(@"Finger down on button %d!", [sender tag]);

    int senderTag = [sender tag];

    for (CBBall *i in balls) {
        int currentTag = [i.button tag];
        if (currentTag == senderTag) {
            i.body -> f = cpvzero;
            [i replaceDynamicBall: i withStaticOneAtLocation: cpBodyGetPos(i.body)];
            [i setIsBeingTouched: YES];
        }
    }
}

- (void) buttonUp: (id) sender
{
    NSLog(@"Finger up on button %d!", [sender tag]);

    int senderTag = [sender tag];

    for (CBBall *i in balls) {
        int currentTag = [i.button tag];
        if (currentTag == senderTag) {
            [i replaceStaticBall: i withDynamicOneAtLocation: cpBodyGetPos(i.body)];
            [i setIsBeingTouched: NO];
        }
    }
}
Luke
  • 9,512
  • 15
  • 82
  • 146

4 Answers4

6

Set the target for UIControlEventAllTouchEvents and then in the targeted method check the value of isTracking property of UIbutton This will solve your problem.

EDIT:

if([btn isTracking])
{
    if(flag)
    {
       flag=NO;
       //Your TouchDown Code
    }
}
else
{
   flag=YES;
   //your Touch Cancel and Exit code
}

and set flag to YES Before

  • But if I do this, how can I differentiate between the Touch Down code, and the Touch Up code? `isTracking` is just a BOOL. – Luke Jan 15 '13 at 13:41
  • 'isTracking' gives YES every time except when the touch is cancelled or exited .So you have to set a flag for the first time call of the targeted method – Sarvajeet Singh Jan 15 '13 at 13:44
  • So, set it to YES the first time it's called, then when can I set it back to NO for subsequent pushes? – Luke Jan 15 '13 at 13:48
  • Do something like this if([btn isTracking]) { if(flag) { flag=NO; //Your TouchDown Code } } else { flag=YES; //your Touch Cancel and Exit code } And set flag to YES Somewhere in the start – Sarvajeet Singh Jan 15 '13 at 13:52
  • This doesn't work, the Touch Cancel code is never called, under any circumstances. – Luke Jan 15 '13 at 14:05
  • The issue relates to the bounds of a `DragExit` event – it needs to be 100px away before it's called. – Luke Jan 15 '13 at 17:06
0

Set the same target to all events you need.

[btn addTarget:self action:@selector(yourMethodtoHandleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[btn addTarget:self action:@selector(yourMethodtoHandleTouchUpInside:) forControlEvents:UIControlEventTouchDragOutside];
[btn addTarget:self action:@selector(yourMethodtoHandleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
Pang
  • 9,564
  • 146
  • 81
  • 122
pradeepa
  • 4,104
  • 5
  • 31
  • 41
0

For cancel touch you can use UIControlEventTouchCancel .

and for b) , i think UIControlEventTouchDragExit should work , i have tried it and its working , make sure you have properly connected the IBAction.

Ankit
  • 1,684
  • 14
  • 14
  • I'm not using IBActions, this is all done programmatically, but no, DragExit is not triggering as it should. – Luke Jan 15 '13 at 12:59
  • I tried by IBAction and it works , can you show the code you are using for adding action / generating Button? – Ankit Jan 15 '13 at 13:52
0

Answering your points

b) dragged off the button, you need to use UIControlEventTouchDragOutside

c) cancelled in some other way, you need ot use UIControlEventTouchCancel

As such:

[newBall.button addTarget:self action:@selector(someMethod:withEvent: )
              forControlEvents: UIControlEventTouchCancel | UIControlEventTouchDragOutside];
Khaled Zayed
  • 306
  • 2
  • 6