I have UICollectionView carousel with UITableView nested inside each UICollectionViewCell.
UICollectionView's layout.scrollDirection = .horizontal, so
- UITableView scroll up/down works fine
- UITableViewCell swipe left/right does not work, but parent UICollectionView scrolling is triggered instead.
How to keep collectionView.isScrollEnabled true, but prioritise UITableViewCell to allow deleting when swiping on it?
Succeeded with another way! Thanks for discussion Claude and for always trying to help!
No success with gestureRecognizer:shouldRequireFailureOfGestureRecognizer: despite the fact it checks really a lot (around 15-20) gesture recognizer pairs, so code would be overcomplicated in my case here. But, anyway, I have another reason why it does not work 👇.
I am using tableView(_:commit:forRowAt:) for row deleting and after testing I've realized that gesture from this method does not being detected at all. So even when I block all gestures in all of collectionView, tableView — swipe on cell is still works.
So, I simply tried gestureRecognizerShouldBegin and it did the job. Here is my solution (zoomed it indicates if collectionView is fullscreen or not). The logic is to check if gesture start point is inside any of tableView rows ( with small gap on left/right to keep ability of collectionView scroll when pan from the sides using insetBy(dx:dy:) ).
extension MyCollectionView: UIGestureRecognizerDelegate {
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard zoomed, let currentCell = currentCell, gestureRecognizer.view is MyCollectionView else { return true }
let cellViews = currentCell.myTableView.visibleCells
let touchPoint = gestureRecognizer.location(in: currentCell.myTableView)
let cellsAtPoint = cellViews.filter {
let localPoint = $0.convert(touchPoint, from: currentCell.myTableView)
return $0.bounds.insetBy(dx: 40, dy: 0).contains(localPoint)
}
return cellsAtPoint.count == 0
}
}