0

I have a UIView subclass named "MyView". In ControllerA, it has a property, MyView *myView, and added it to self.view. On myView, there are some random subviews sliding from right to left, and then disappears. What I want to do is, when the user tap one of the sliding subview, identify that view, and push another controller.

In MyView.m I overrided touchesBegan, touchesEnded, touchesCanceled, and add NSLog in each method. In touchesEnded methds, I use the code below to identify the subview being tapped:

UITouch *touch = [touches anyObject];
CGPoint touchLoaction = [touch locationInView:self];
for (UIView *subview in self.subviews) {
    if ([subview.layer.presentationLayer hitTest:touchLoaction]) {
        if (_delegate && [_delegate respondsToSelector:@selector(canvas:didSelectView:)]) {
            [_delegate canvas:self didSelectView:subview];
        }
        break;
    }
}

My operation steps are:

  1. When I tap one subview, the log is: began, ended. And then pushed to controllerB.

  2. When I pop back to controllerA, and tap one subview, the log is: began, cancelled, and didn't push to controllerB because touchesEnded didn't get called.

  3. When tap the subview again, the log is: began, ended, and then pushed to controllerB.

I suspect the reason was because of the push, so I commented out the 'identifying' code in touchesEnded method, now, when I tap a subview, the log is always: began, ended.

So my question is, why touchesEnded method didn't get called in step 2?

I tried to use performSelector:afterDelay: to delay the push, but it doesn't help. When I pop back and tap a subview, it is always touchesCancelled method get called, and then I tap again, then touchesEnded get called.

Can any one help me with this? Thanks in advance and best wishes!

Fabio Berger
  • 1,921
  • 2
  • 24
  • 29
longbow
  • 362
  • 2
  • 14

2 Answers2

2

Check if you have gesture recognition active on any of the view controllers involved and if so turn it off. Recognizers tend to cancel touches in some cases. From your description I understand you are not using gesture recognizers anyway.

Rudi Angela
  • 1,463
  • 1
  • 12
  • 20
  • Thanks for the answer, but we've found that it's because another module did some thing when this view appears. It added a tap gesture recognizer on the view, so that's the reason. – longbow Jan 12 '16 at 07:13
1

Instead of using touchesBegan, touchesEnded and touchesCanceled, why don't you set UIGestureRecognizers to each subview? Once done that, you can also catch events before they happen implementing the UIGestureRecognizerDelegate methods for more granularity.

- (void)viewDidLoad {

    [super viewDidLoad];

    // Add the delegate to the tap gesture recognizer

    self.tapGestureRecognizer.delegate = self;

}



// Implement the UIGestureRecognizerDelegate method

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    // Determine if the touch is inside the custom subview

    if ([touch view] == self.customSubview){

        // If it is, prevent all of the delegate's gesture recognizers

        // from receiving the touch

        return NO;

    }

    return YES;

}
chuckSaldana
  • 1,187
  • 12
  • 28