UIPageViewController — это компонент пользовательского интерфейса iOS, который предлагает удобный способ навигации между последовательными страницами контента. Он использует постраничную модель представления, позволяющую пользователям пролистывать страницы влево или вправо с помощью жестов.
Особенно полезен в приложениях, где контент должен быть представлен в формате, напоминающем физические страницы. Например, в приложениях для чтения книг, образовательных курсах, галереях изображений или даже в некоторых типах интерактивных руководств. UIPageViewController обеспечивает дополнительный уровень привлекательности и удобства использования приложения.
Сегодня я хочу поделиться кратким и простым руководством о том, как просто и программно реализовать UIPageViewController. Итак, что же мы получим в итоге?

Для начала определим класс ContentViewController, который реализует собственный контроллер представления. Этот класс предназначен для использования в UIPageViewController, где каждая страница представлена экземпляром ContentViewController. Это позволяет легко создавать несколько страниц с различными цветами текста и фона:
class ContentViewController: UIViewController { private lazy var textLabel: UILabel = { let label = UILabel() label.textAlignment = .center label.textColor = .white label.font = UIFont.systemFont(ofSize: 25, weight: .bold) label.translatesAutoresizingMaskIntoConstraints = false return label }() override func viewDidLoad() { super.viewDidLoad() setupViews() setupConstraints() } private func setupViews() { view.addSubview(textLabel) } private func setupConstraints() { NSLayoutConstraint.activate([ textLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), textLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor), textLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8) ]) } func configure(with text: String, backgroundColor: UIColor) { textLabel.text = text view.backgroundColor = backgroundColor } }
configure(with:backgroundColor:):
Этот метод позволяет настроить textLabel и цвет фона контроллера снаружи. Параметр text используется для установки текста в textLabel, а backgroundColor - для установки цвета фона view
Теперь создадим класс PageViewController, который наследуется от UIPageViewController. Этот класс эффективно управляет созданием и отображением различных страниц, каждая из которых представлена экземпляром ContentViewController с настраиваемым цветом текста и фона:
class PageViewController: UIPageViewController { var pages: [ContentViewController] = [] override func viewDidLoad() { super.viewDidLoad() self.dataSource = self let pageData: [(String, UIColor)] = [ ("Let's", .paleLavender), ("Get", .paleTurquoise), ("Started", .paleGreen) ] for (text, color) in pageData { let contentVC = ContentViewController() contentVC.configure(with: text, backgroundColor: color) pages.append(contentVC) } if let firstPage = pages.first { setViewControllers([firstPage], direction: .forward, animated: true, completion: nil) } } }
Что мы здесь делаем:
Создаем массив пустых страниц pages, который будет содержать экземпляры ContentViewController
Создаем массив кортежей pageData [(String, UIColor)], где каждый кортеж содержит строку и цвет. Эти данные используются для настройки каждой страницы в UIPageViewController
Проходим циклом по каждому элементу pageData (где каждый элемент - это кортеж) и для каждого элемента создаем новый экземпляр ContentViewController, далее вызывает метод configure для настройки contentVC и добавляем сконфигурированный contentVC в массив pages
Далее проверяем, находится ли первая страница в массиве страниц. Если страница существует, она устанавливается в качестве текущего активного контроллера в UIPageViewController
Устанавливает сам PageViewController в качестве источника данных (dataSource) для UIPageViewController. Это необходимо для управления содержимым страниц.
Все, что нам осталось сделать, это реализовать протокол UIPageViewControllerDataSource, который используется для предоставления контроллеров представления, которые будут отображаться в UIPageViewController:
extension PageViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let contentVC = viewController as? ContentViewController, let currentIndex = pages.firstIndex(of: contentVC), currentIndex > 0 else { return nil } return pages[currentIndex - 1] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let contentVC = viewController as? ContentViewController, let currentIndex = pages.firstIndex(of: contentVC), currentIndex < pages.count - 1 else { return nil } return pages[currentIndex + 1] } }
Эти два метода обеспечивают логику отображения контроллера и плавную и последовательную навигацию между страницами.
Рассмотрим каждый метод подробно:
pageViewController(_:viewControllerBefore:):
Этот метод определяет, какой контроллер должен быть показан перед текущим контроллером в
UIPageViewControllerguard letпроверяет, что текущий контроллер является экземпляромContentViewControllerи определяет его текущий индекс в массивеpagescurrentIndex > 0гарантирует, что теку��ий контроллер не является первым в массиве, что позволяет избежать выхода за пределы массиваЕсли условие выполняется, метод возвращает контроллер представления, который находится перед текущим (
pages[currentIndex - 1]). Если условие не выполняется, метод возвращаетnil, указывая, что предыдущего контроллера нет
pageViewController(_:viewControllerAfter:):
Этот метод определяет, какой контроллер должен отображаться после текущего контроллера в
UIPageViewControllerАналогично первому методу,
guard letпроверяет, что текущий контроллер является экземпляромContentViewControllerи определяет его индексcurrentIndex < pages.count - 1проверяет, что текущий контроллер не является последним в массивеЕсли условие выполняется, метод возвращает следующий контроллер представления (
pages[currentIndex + 1]). Если нет, то возвращаетnil, указывая на отсутствие следующего контроллера
Добавляем в App или Scene:
let pageViewController = PageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: nil) window?.rootViewController = pageViewController
PageViewController предлагает различные стили перехода и ориентации навигации:
Параметры TransitionStyle: параметр .pageCurl имитирует эффект перелистывания настоящей книги или журнала, .scroll предоставляет опцию, при которой страницы скользят горизонтально или вертикально.
NavigationOrientation определяет, будет ли пользователь перемещаться по страницам горизонтально или вертикально.
