Skip to content

Instantly share code, notes, and snippets.

@oconnelltoby
Created March 9, 2021 17:15
Show Gist options
  • Save oconnelltoby/d7d62e8e8ae114e875641150cc27e00f to your computer and use it in GitHub Desktop.
Save oconnelltoby/d7d62e8e8ae114e875641150cc27e00f to your computer and use it in GitHub Desktop.
PageViewController
import UIKit
class PageViewController: UIPageViewController {
private let firstItem: UIViewController
private var pages: [UIViewController]
private let pageChanged: (_ index: Int) -> Void
let strongDelegate: UIPageViewControllerDelegate
let strongDataSource: UIPageViewControllerDataSource
init(_ firstItem: UIViewController, _ otherItems: [UIViewController], pageChanged: @escaping (_ index: Int) -> Void) {
self.firstItem = firstItem
self.pages = [firstItem] + otherItems
self.pageChanged = pageChanged
strongDelegate = PageViewControllerDelegate(pages: pages, pageChanged: pageChanged)
strongDataSource = PageViewControllerDataSource(pages: pages)
super.init(transitionStyle: .scroll, navigationOrientation: .horizontal)
delegate = strongDelegate
dataSource = strongDataSource
}
convenience init(_ firstItem: UIViewController, _ otherItems: UIViewController..., pageChanged: @escaping (_ index: Int) -> Void) {
self.init(firstItem, otherItems, pageChanged: pageChanged)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
setViewControllers([firstItem], direction: .forward, animated: false)
}
override func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewController.NavigationDirection, animated: Bool, completion: ((Bool) -> Void)? = nil) {
super.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
guard let currentViewController = viewControllers?.first else { return }
guard let index = pages.firstIndex(of: currentViewController) else { return }
pageChanged(index)
}
}
class PageViewControllerDataSource: NSObject, UIPageViewControllerDataSource {
private let pages: [UIViewController]
init(pages: [UIViewController]) {
self.pages = pages
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.firstIndex(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard pages.count > previousIndex else {
return nil
}
return pages[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.firstIndex(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = pages.count
guard orderedViewControllersCount != nextIndex else {
return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return pages[nextIndex]
}
}
class PageViewControllerDelegate: NSObject, UIPageViewControllerDelegate {
private let pages: [UIViewController]
private let pageChanged: (_ index: Int) -> Void
init(pages: [UIViewController], pageChanged: @escaping (_ index: Int) -> Void) {
self.pages = pages
self.pageChanged = pageChanged
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let currentViewController = pageViewController.viewControllers?.first else { return }
guard let index = pages.firstIndex(of: currentViewController) else { return }
pageChanged(index)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment