When I do fast swipe between pages sometimes I get duplicate pages. My index counting may be wrong, but I tried everything and always get the same.
DetailedProfileViewController.swift
class DetailedProfileViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var currentProfileIndex : Int?
var nextProfileIndex :Int?
var data: Main?
var mainPageView : UIPageViewController!
override func viewDidLoad() {
super.viewDidLoad()
let profile = ProfileViewController()
profile.profile = currentProfile()
let arraysOfViews = [profile]
mainPageView = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])
mainPageView.setViewControllers(arraysOfViews, direction: .forward, animated: true, completion: nil)
mainPageView.dataSource = self
mainPageView.delegate = self
addChildViewController(mainPageView)
view.addSubview(mainPageView.view)
mainPageView.didMove(toParentViewController: self)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if currentProfileIndex == (data?.filteredProfiles.count)!-1 { return nil }
nextProfileIndex = abs((currentProfileIndex! + 1) % (data?.filteredProfiles.count)!)
let profile = ProfileViewController()
profile.profile = data?.filteredProfiles[nextProfileIndex!]
return profile
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if currentProfileIndex == 0 { return nil }
nextProfileIndex = abs((currentProfileIndex! - 1) % (data?.filteredProfiles.count)!)
let profile = ProfileViewController()
profile.profile = data?.filteredProfiles[nextProfileIndex!]
return profile
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed == true {
currentProfileIndex = nextProfileIndex
}
}
}
I'm not setting all of View Controllers in viewDidLoad because it could be hundreds of them..
The dumbest solution is to add an index
to ProfileViewController
. If you do so, you can set it as zero to the first page. And whenever you are asked to provide the next or previous view controller, you always know relatively to what index, because you may extract it from the given pageViewController
(which is in fact your ProfileViewController
).
Otherwise the handling of the currentProfileIndex
may be very error-prone.
UPDATE
class DetailedProfileViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var data: Main?
var mainPageView : UIPageViewController!
override func viewDidLoad() {
super.viewDidLoad()
let profile = ProfileViewController()
profile.index = 0
profile.profile = currentProfile()
let arraysOfViews = [profile]
mainPageView = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])
mainPageView.setViewControllers(arraysOfViews, direction: .forward, animated: true, completion: nil)
mainPageView.dataSource = self
mainPageView.delegate = self
addChildViewController(mainPageView)
view.addSubview(mainPageView.view)
mainPageView.didMove(toParentViewController: self)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let pagesCount = data?.filteredProfiles.count else {
return nil
}
guard let newIndex = (viewController as? ProfileViewController).index + 1, newIndex < pagesCount else {
return nil
}
let profile = ProfileViewController()
profile.profile = data?.filteredProfiles[newIndex]
profile.index = newIndex
return profile
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let pagesCount = data?.filteredProfiles.count else {
return nil
}
guard let newIndex = (viewController as? ProfileViewController).index - 1, newIndex >= 0 else {
return nil
}
let profile = ProfileViewController()
profile.profile = data?.filteredProfiles[newIndex!]
profile.index = newIndex
return profile
}
}