UITableView inside UIScrollView not receiving first tap after scrollling

ios, objective-c, uiscrollview, uitableview

Solution

leave the inner UITableView's `scrollEnabled` property set as `YES`. this lets the inner `UITableView` know to handle scroll-related touches on the `UIScrollView` correctly.

Problem

Brief I am having an issue with a `UITableView` inside a `UIScrollView`. When I scroll the external `scrollView`, the `table` does not receive the `willSelect/didSelect` event on the first touch, but it does on the second one. What is even more strange, the cell itself gets the touches and the highlighted state, even when the `delegate` does not. Detailed explanation My view hierarchy: ``` UIView - UIScrollView (outerscroll) - Some other views and buttons - UITableView (tableView) ``` Inside the scroll view I have some extra views that get expanded/closed dynamically. The table view needs to get "fixed" on top, together with some other elements of the view, so that is why I created this layout, that allows me to easily move elements in a similar way than Apple recommends by the use of transformations when the scroll happens. The table View is transformed with a translation effect when the outerscroll moves like this: ``` - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == self.outerScrollView) { CGFloat tableOffset = scrollView.contentOffset.y - self.fixedHeaderFrame.origin.y; if (tableOffset > 0) { self.tableView.contentOffset = CGPointMake(0, tableOffset); self.tableView.transform = CGAffineTransformMakeTranslation(0, tableOffset); } else { self.tableView.contentOffset = CGPointMake(0, 0); self.tableView.transform = CGAffineTransformIdentity; } // Other similar transformations are done here, but not involving the table } ``` In my cell, if I implement these methods: ``` - (void)setSelected:(BOOL)selected { [super setSelected:selected]; if (selected) { NSLog(@"selected"); } } - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; if (highlighted) { NSLog(@"highlighted"); } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; NSLog(@"touchesBegan"); } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; NSLog(@"touchesEnded"); } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; NSLog(@"touchesCancelled"); } ``` Y can see this output when fails (first tap): ``` 2014-02-10 13:04:40.940 MyOrderApp[5588:70b] highlighted 2014-02-10 13:04:40.940 MyOrderApp[5588:70b] touchesBegan 2014-02-10 13:04:40.978 MyOrderApp[5588:70b] touchesEnded ``` And this one when works (second tap): ``` 2014-02-10 13:05:30.359 MyOrderApp[5588:70b] highlighted 2014-02-10 13:05:30.360 MyOrderApp[5588:70b] touchesBegan 2014-02-10 13:05:30.487 MyOrderApp[5588:70b] touchesEnded 2014-02-10 13:05:30.498 MyOrderApp[5588:70b] expanded ``` No other frame change, animation or any other view interaction is done between the first and the second tap. Also, only when scrolling large amounts the bug appears, but with scrollings of just a few pixels everything keeps working as expected. I experimented changing some properties as well, but with no luck. Some of the things I did: - Remove `userInteractionEnabled` from views other than the scroll and table - Add a call to `setNeedsLayout` on the table, scroll and main view when `scrollViewDidScroll` occurs. - Remove the transformations from the table (still happens) I have seen some comments about the unexpected behaviour of embedding `UITableViews` inside `UIScrollViews` but I can not see such a warn in the official documentation by Apple, so I am expecting it to work. The app is iOS7+ only. Questions Has anyone experienced similar issues? Why is this and how can I solve it? I think that I could be able to intercept the tap gesture on the cell and pass it with a custom delegate or similar, but I would like the table to receive the proper events and so my `UITableViewDelegate` receives it as expected. Updates - I tried disabling cell reuse as suggested in a comment but it still happens in the same way.

Original source