Created
March 9, 2021 17:15
-
-
Save oconnelltoby/d7d62e8e8ae114e875641150cc27e00f to your computer and use it in GitHub Desktop.
PageViewController
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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