Почему UIPageViewController внутри UIScrollView первый свайп фейлится?

UIPageViewController - это контроллер, который позволяет создавать пейджинговые пользовательские интерфейсы, в которых пользователь может листать страницы свайпом. По умолчанию, UIPageViewController сам управляет своим внутренним UIScrollView, который обеспечивает скроллинг между страницами.

Одна из причин, почему первый свайп может "фейлиться" заключается в том, что UIPageViewController имеет встроенную функциональность, позволяющую пользователю листать страницы горизонтально свайпом. Это конфликтует с возможностью свайпа вертикально, которую обеспечивает UIScrollView.

Когда пользователь делает свайп вверх или вниз, UIScrollView начинает прокрутку контента вертикально, но затем обнаруживает, что есть также возможность свайпа горизонтально, и пытается начать прокрутку между страницами. Но так как первый свайп был уже засчитан как вертикальный, UIPageViewController интерпретирует это как завершенный свайп, и ничего не происходит.

Есть несколько способов решить эту проблему:

1. Отключить горизонтальный свайп UIPageViewController'а:

   pageViewController.isPagingEnabled = false

2. Отключить вертикальный свайп UIScrollView:

   pageViewController.scrollView?.isScrollEnabled = false

3. Обработать каждое нажатие на экран и определить, какой тип свайпа сделал пользователь. Если свайп вертикальный - обрабатывать его, если горизонтальный - передавать его UIPageViewController.

Для этого можно использовать UIGestureRecognizerDelegate или следить за свайпами, например, в методе touchesMoved(_:with:) контроллера, в котором содержится UIPageViewController.

   override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
       // Получаем координаты тача и вычисляем разность с предыдущей позицией
       let touch = touches.first!
       let currentLocation = touch.location(in: self.view)
       let previousLocation = touch.previousLocation(in: self.view)
       let deltaX = currentLocation.x - previousLocation.x
       let deltaY = currentLocation.y - previousLocation.y
       
       // Если разница X больше, чем разница Y, передаем свайп UIPageViewController'у
       if abs(deltaX) > abs(deltaY) {
           pageViewController.scrollView?.isScrollEnabled = true
       } else {
           pageViewController.scrollView?.isScrollEnabled = false
       }
       
       super.touchesMoved(touches, with: event)
   }

Теперь пользователь может свайпать вверх и вниз, и UIPageViewController не будет "фейлить" первый свайп.