Skip to content

Instantly share code, notes, and snippets.

@mntone
Created August 27, 2019 00:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mntone/a0a6b81688bcfa26251b3c0afcc8d16e to your computer and use it in GitHub Desktop.
Save mntone/a0a6b81688bcfa26251b3c0afcc8d16e to your computer and use it in GitHub Desktop.
import UIKit
final class PageViewControllerSegmentedAdapter: NSObject {
private unowned let pageViewController: UIPageViewController
private unowned let segmentControl: UISegmentedControl
private let viewControllers: [UIViewController]
private var selectedIndex: Int
init(pageViewController: UIPageViewController, segmentControl: UISegmentedControl, viewControllers: [UIViewController], at selectedIndex: Int = 0) {
assert(segmentControl.numberOfSegments == viewControllers.count)
self.pageViewController = pageViewController
self.segmentControl = segmentControl
self.viewControllers = viewControllers
self.selectedIndex = selectedIndex
super.init()
pageViewController.delegate = self
pageViewController.dataSource = self
if viewControllers.count > selectedIndex {
let targetViewController = viewControllers[selectedIndex]
pageViewController.setViewControllers([targetViewController], direction: .forward, animated: false)
}
segmentControl.selectedSegmentIndex = selectedIndex
segmentControl.addTarget(self, action: #selector(segmentControlValueChanged), for: .valueChanged)
}
@objc private func segmentControlValueChanged() {
let selectedIndex = self.selectedIndex
let selectedSegmentIndex = segmentControl.selectedSegmentIndex
if selectedSegmentIndex > selectedIndex {
let nextIndex = selectedIndex + 1
for index in nextIndex...selectedSegmentIndex {
setViewController(at: index, direction: .forward)
}
} else if selectedSegmentIndex < selectedIndex {
let previousIndex = selectedIndex - 1
for index in (selectedSegmentIndex...previousIndex).reversed() {
setViewController(at: index, direction: .reverse)
}
}
}
private func setViewController(at index: Int, direction: UIPageViewController.NavigationDirection) {
pageViewController.setViewControllers([viewControllers[index]], direction: direction, animated: true) { [weak self] completed in
guard let me = self else {
return
}
if completed {
me.selectedIndex = index
}
}
}
}
// MARK: - UIPageViewControllerDelegate
extension PageViewControllerSegmentedAdapter: UIPageViewControllerDelegate {
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let index = self.viewControllers.firstIndex(of: viewController), index > 0 else {
return nil
}
return self.viewControllers[index &- 1]
}
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard var index = self.viewControllers.firstIndex(of: viewController) else {
return nil
}
index = index &+ 1
guard index < self.viewControllers.count else {
return nil
}
return self.viewControllers[index]
}
}
// MARK: - UIPageViewControllerDataSource
extension PageViewControllerSegmentedAdapter: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
guard let viewControllers = pageViewController.viewControllers,
let lastViewController = viewControllers.last,
let index = self.viewControllers.firstIndex(of: lastViewController) else {
return
}
if finished, completed {
self.selectedIndex = index
self.segmentControl.selectedSegmentIndex = self.selectedIndex
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment