How to cancel a sequence of UITouch events?

2019-01-25 03:27发布

I have a UIImage view that responds to touch events. I want to cancel the touch sequence, i.e., further calls to touchesMoved:, if the touch goes outside of certain bounds. How can I do that?

I know that in touchesMoved: I can inspect the coordinates of the touch object and ignore it, but what I don't know is how to cancel the sequence altogether. I don't see any method documented in the Apple Developer UIResponder Reference that I can call to cancel a touch sequence.

12条回答
Ridiculous、
2楼-- · 2019-01-25 04:21

I achieve this by removing the view from its superview and adding it straight back.

[view retain];
UIView *sv = view.superview;
[view removeFromSuperview];
[sv addSubview:view];
[view release];

This breaks the responder chain to the view so any remaining touches will not be received on the view. The next touch will still be received as normal.

查看更多
够拽才男人
3楼-- · 2019-01-25 04:25

You can check that, the touch point locations are in CGRect (ie. points are in Rectangle of your imageview) or not. If they are not in that Rect, the touch will be cancelled.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
 {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];

    if (CGRectContainsPoint(myImageView, touchLocation))
    {
       lastPoint = [touch locationInView: myImageView];
    }

    NSLog(@"Last :%.2f - %.2f",lastPoint.x, lastPoint.y);   
  }

 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
 {
  CGPoint currentPoint;
  UITouch *touch = [touches anyObject];
  CGPoint touchLocation = [touch locationInView:self.view];

     if (CGRectContainsPoint(myImageView.frame, touchLocation))
     {
       currentPoint = [touch locationInView: myImageView];
     }
 }
查看更多
对你真心纯属浪费
4楼-- · 2019-01-25 04:27

On iOS5 there seems to be a private method in UITouch

-(void)setSentTouchesEnded:(BOOL)ended;

Depending on apple's implementation it could stop sending events

Another way of doing so would be using associative objects

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if ([(NSNumber *)objc_getAssociatedObject(touch, &outKey) boolValue])
        return;
    if (sometouchisoutsideofview) {
        objc_setAssociatedObject(touch, &outKey, [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN);
    }
}
查看更多
手持菜刀,她持情操
5楼-- · 2019-01-25 04:29

I've faced the same problem recently and found a standard way to solve it. You can use [[UIApplication sharedApplication] beginIgnoringInteractionEvents] to stop delivering touchesMoved events to your whole app. Make sure to enable them using [[UIApplication sharedApplication] endIgnoringInteractionEvents] when you need to receive touches again.

查看更多
仙女界的扛把子
6楼-- · 2019-01-25 04:29

I don't think it's possible because I don't see it documented and none of these solutions work.

查看更多
你好瞎i
7楼-- · 2019-01-25 04:31

You need to call [super touchesMoved:withEvent:] in order to let the super view clean up from the event but more importantly, you need to not call [super touchesCancelled:withEvent:].

Here's what I used on a cell to keep it from getting selected when I detected a swipe:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!showingEdit) {
        if (IS_FAR_ENOUGH_TO_BE_A_SWIPE) {
            RESPOND_TO_SWIPE
            showingEdit = YES;
            [super touchesCancelled:touches withEvent:event];
        } else {
            [super touchesMoved:touches withEvent:event];
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!showingEdit) {
        [super touchesEnded:touches withEvent:event];
    }
}
查看更多
登录 后发表回答