Search code examples
iosobjective-ccocoa-touchtouch-eventuicontrolevents

Detect a finger after TouchDown leaving the control, before TouchUp


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];
        }
    }
}

Solution

  • 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