4
votes

I am using UIPanGestureRecognizer to recognize drag movement of an object and it works fine for the following states:

UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[panGesture setMaximumNumberOfTouches:1];
[panGesture setDelegate:self];
[self.view addGestureRecognizer:panGesture];
[panGesture release];

- (void)panAction:(UIPanGestureRecognizer *)gR 
{
    switch (gR.state) 
    {       
        case UIGestureRecognizerStateBegan:
            NSLog(@"drag began");
            break;

        case UIGestureRecognizerStateChanged:
            NSLog(@"drag moved");
            break;

        case UIGestureRecognizerStateEnded:
            NSLog(@"drag ended");
            break;

        default:
            break;
    }
}

Now my question is, is it possible to detect the situation where the user has began dragging the object and at some point has stopped dragging and held the object into a fixed point? I've checked that the when the user stops moving the object it stops logging "changed" until the user starts moving the object or releases it (in that case it logs "ended"). Here is a example log:

2013-02-19 16:36:**01.181** Project[24201:10a03] drag began
2013-02-19 16:36:**14.004** Project[24201:10a03] drag moved
2013-02-19 16:36:14.221 Project[24201:10a03] drag moved
2013-02-19 16:36:**14.894** Project[24201:10a03] drag ended

You can see there are some pauses between began, changed and ended (that time the object was held fixed at a point). Is it possible to detect that situation? If so, how? Any help would be cordially appreciated, thanks in advance.

Update

I've tried UILongPressGestureRecognizer:

UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];
[longPressGesture setDelegate:self];
[self.view addGestureRecognizer:longPressGesture];
[longPressGesture release];

-(void)handleLongPressGesture:(UILongPressGestureRecognizer *)gR
{
    switch (gR.state)
    {
        case UIGestureRecognizerStateBegan:
            NSLog(@"long press began");
            break;

        case UIGestureRecognizerStateCancelled:
            NSLog(@"long press cancelled");
            break;

        case UIGestureRecognizerStateEnded:
            NSLog(@"long press ended");
            break;

        default:
            break;
    }
}

And also the delegate method:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

Now, both recognizers are recognized separately. If the long press gesture is acted first, both the gestures are recognized simultaneously:

2013-02-19 17:19:13.382 Project[24357:10a03] long press began
2013-02-19 17:19:14.901 Project[24357:10a03] drag began
2013-02-19 17:19:14.937 Project[24357:10a03] drag moving
2013-02-19 17:19:15.025 Project[24357:10a03] drag moving
2013-02-19 17:19:16.317 Project[24357:10a03] long press ended
2013-02-19 17:19:16.317 Project[24357:10a03] drag ended

But if the drag gesture is acted first, it does not recognize the long press anymore unless the drag is ended:

2013-02-19 17:21:05.985 Project[24357:10a03] drag began
2013-02-19 17:21:06.001 Project[24357:10a03] drag moving
2013-02-19 17:21:06.018 Project[24357:10a03] drag moving
2013-02-19 17:21:**06.052** Project[24357:10a03] drag moving
2013-02-19 17:21:**17.786** Project[24357:10a03] drag moving
2013-02-19 17:21:17.818 Project[24357:10a03] drag moving
2013-02-19 17:21:17.851 Project[24357:10a03] drag moving
2013-02-19 17:21:19.324 Project[24357:10a03] drag ended
2013-02-19 17:21:20.388 Project[24357:10a03] long press began
2013-02-19 17:21:21.188 Project[24357:10a03] long press ended

I need the second case to detect long press after drag has started.

1

1 Answers

2
votes

You can schedule an NSTimer on UIGestureRecognizerStateChanged after invalidating it if it exists, then do whatever you want to in the timer's selector.

if(self.myTimer)
     [self.myTimer invalidate];
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:PAUSE_INTERVAL target:self selector:@selector(userPaused:) userInfo:nil repeats:NO];