12

I am adding UIScrollView in UITableViewCell, but when I am click on scroll view did select method is not getting called.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

I am adding the scroll view on contentView of cell, still its not calling did select method.

 [cell.contentView addSubview:scrollView];
tshepang
  • 12,111
  • 21
  • 91
  • 136
vntstudy
  • 2,038
  • 20
  • 24

3 Answers3

30

The reason your table cell is not being able to detect the touches is because the scrollView on your cell is intercepting the touches and is not conveying it to the table cell so that the tableView delegate function can be called.

A simpler fix is just create a subclass of UIScrollView and set the scrollView on your cell to this subclass. override these methods on the scrollview subclass

-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
        if (!self.dragging)
            [self.superview touchesCancelled: touches withEvent:event];
        else
            [super touchesCancelled: touches withEvent: event];
    }

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
            if (!self.dragging)
                [self.superview touchesMoved: touches withEvent:event];
            else
                [super touchesMoved: touches withEvent: event];
        }

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
            if (!self.dragging)
                [self.superview touchesBegan: touches withEvent:event];
            else
                [super touchesBegan: touches withEvent: event];
        }

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
            if (!self.dragging)
                [self.superview touchesEnded: touches withEvent:event];
            else
                [super touchesEnded: touches withEvent: event];
        }

Which basically checks whether the scroll view is being dragged , and if its not it passes all the touch events to its superview , in this case the cell content view.

This fixed a similar problem for me , hope this helps.

Cheers.

NavinDev
  • 995
  • 1
  • 7
  • 8
  • 1
    This is a much better solution than the gesture recognizer one posted above. – Hesham Oct 21 '14 at 15:50
  • 1
    This is a much better solution and should be the answer. :) – Johnny Dec 16 '14 at 10:13
  • Amazing! I already thought of something like this, but you just provided a drop-in solution, definitely brilliant and simple :) – Julian F. Weinert Jul 24 '15 at 21:53
  • @NavinDev This works if I create a sample project. But does not work on my application where I have tabbarcontrollers with its delegate set. Any reason for it to not work? – Deepak Thakur Feb 29 '16 at 07:44
  • @NavinDev I figured out that if you have uitapgesturerecogniser somewhere in your code for other functionality, this will not work. But main purpose of the question is achieved!! – Deepak Thakur Feb 29 '16 at 09:32
15

Because scrollView overlapped on Cell... Best way is add tap Gesture on UIScrollView such like,

UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureAction:)];
[recognizer setNumberOfTapsRequired:1];
MYScrollView.userInteractionEnabled = YES;
[MYScrollView addGestureRecognizer:recognizer];

Add above code in cellForRowAtIndexPath method and Write gesture action method such like

-(void)gestureAction:(UITapGestureRecognizer *) sender
{
    CGPoint touchLocation = [sender locationOfTouch:0 inView:self.YourTableViewName];
    NSIndexPath *indexPath = [self.YourTableViewName indexPathForRowAtPoint:touchLocation];

    NSLog(@"%d", indexPath.row);
}

Here in above gesture (action) method you can get indexPath as same as didSelectRowAtIndexPath.

iPatel
  • 46,010
  • 16
  • 115
  • 137
  • This solution feels wrong but it works in case you have only one tableview inside scrollview. What if we have multiple tableview / collectionview ? Lots of ecommerce apps have multiple collectionviews inside scrollview. This solution won't work in that case. – Deepak Thakur Feb 29 '16 at 06:53
14

Swift 2

class UIScrollViewSuperTaps: UIScrollView {
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if self.dragging {
            super.touchesBegan(touches, withEvent: event)
        } else {
            self.superview?.touchesBegan(touches, withEvent: event)
        }
    }

    override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
        if self.dragging {
            super.touchesCancelled(touches, withEvent: event)
        } else {
            self.superview?.touchesCancelled(touches, withEvent: event)
        }
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if self.dragging {
            super.touchesEnded(touches, withEvent: event)
        } else {
            self.superview?.touchesEnded(touches, withEvent: event)
        }
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if self.dragging {
            super.touchesMoved(touches, withEvent: event)
        } else {
            self.superview?.touchesMoved(touches, withEvent: event)
        }
    }
}

Swift 3

class UIScrollViewSuperTaps: UIScrollView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if self.isDragging {
            super.touchesBegan(touches, with: event)
        } else {
            self.superview?.touchesBegan(touches, with: event)
        }
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)    {
        if self.isDragging {
            super.touchesCancelled(touches, with: event)
        } else {
            self.superview?.touchesCancelled(touches, with: event)
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if self.isDragging {
            super.touchesEnded(touches, with: event)
        } else {
            self.superview?.touchesEnded(touches, with: event)
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if self.isDragging {
            super.touchesMoved(touches, with: event)
        } else {
            self.superview?.touchesMoved(touches, with: event)
        }
    }
}

Don't forget to assign class UIScrollViewSuperTaps to your scroll view in storyboard or in code depending on how you created it.

Valentin Shamardin
  • 3,569
  • 4
  • 34
  • 51
Maklaus
  • 538
  • 2
  • 16
  • 37