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 | |
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