The problem


In the project encountered a horizontal UIScrollView nested two TableViews, and the right TableView needs to support the need to swipe left to delete cells.

Conventional scheme


Find a circle of solutions, mostly inherit a UIScrollveiw, rewrite the subclass

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
 if(gestureRecognizer.state ! =UIGestureRecognizerStatePossible) {
 return YES;
 } else {
 return NO; }}Copy the code

The method return YES allows the gesture to be recognized by both the ScrollView and the TableView.

But because the project already uses UIPageViewController, you can’t inherit a UIscrollView. Along this line of thought, define a UIScrollView subclasses, set pageViewController. The scrollview. PanGestureRecognizer. Delegate = subclasses. Rewrite subclass

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Copy the code

The message forwarding mechanism is used to transfer the other subclass methods to the original ScrollView. But this approach has been vetoed by APPLE, APPLE does not allow us to modify the scrollview. PanGestureRecognizer. Delegate.

Final solution


The final solution was to add a Gesture recognizer to the TableView,

  1. So first we get the scrollView of UIPageViewController
UIScrollView *scrollView = nil;
    for (UIView *view in self.view.subviews) {
        if ([view isKindOfClass:[UIScrollView class]]) {
            scrollView = (UIScrollView *)view;
            break; }}Copy the code
  1. Add a panGestureRecognizer to the TableView and set the gesture response priority. When the TableView responds to the gesture, the ScrollView does not respond to the gesture
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
    panGesture.delaysTouchesBegan = YES;
    panGesture.cancelsTouchesInView = NO;
    panGesture.delegate = self;

    [self.tableView addGestureRecognizer:panGesture];
    self.scrollView.canCancelContentTouches = YES;
    [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:panGesture];
Copy the code
  1. Implementing proxy methods

This method is called when the Gesture recognizer transitions from the possible state to something else.

The return NO method causes the Gesture recognizer to enter the failed state and the gesture is NO longer recognized.

X is negative when you swipe from right to left to delete the cell, so when translation.x < 0, give the method return YES to continue recognizing the cell swipe to delete gesture. If swiping from left to right, with translation. X being positive, the method returns NO, and tableveiw’s Gesture recognizer enters a failed state, and the ScrollView recognises the gesture and slides to the left TableView.

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if(! [gestureRecognizer isMemberOfClass:[UIPanGestureRecognizer class]]) {
        return NO;
    }
    UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer;
    CGPoint translation = [panGesture translationInView:self.tableView];
    return translation.x < 0;
}
Copy the code

Return YES allows both tableView and ScrollView to recognize gestures

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return otherGestureRecognizer.view == self.tableView;
}
Copy the code