swift: How to create UIPageViewController? - ios

I want to create UIPageViewController with spine mid location. I read several tutorials with UIPageViewController but in this tutorials used spine min or max location. And I can not create UIPageViewController with spine mid location.
I have this function to create UIPageViewController with spine mid location min or max location:
func createPageViewController() {
// Instantiate the PageViewController
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.dataSource = self
pageController.delegate = self
if images.count > 0{
let contentController = getContentViewController(withIndex: 0)!
let contentControllers = [contentController]
pageController.setViewControllers(contentControllers, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
pageViewController = pageController
self.addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMove(toParentViewController: self)
}
I tried to change it for this:
let contentController = getContentViewController(withIndex: 0)!
let contentController1 = getContentViewController(withIndex: 1)!
let contentControllers = [contentController, contentController1]
But in this case my images not showing in pages. It is not help. What am I doing wrong? How to create UIPageViewController with spine mid location?
Update
import UIKit
class PageViewController: UIViewController {
#IBOutlet weak var PageControl: UIPageControl!
var pageViewController: UIPageViewController?
var images = ["book1page1.png","book1","book1","book1page2.png","book1page1.png","book1page2.png"]
var pendingIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControll()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createPageViewController() {
// Instantiate the PageViewController
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.dataSource = self
pageController.delegate = self
if images.count > 0{
let firstController = getContentViewController(withIndex: 0)!
let contentControllers = [firstController]
pageController.setViewControllers(contentControllers, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
pageViewController = pageController
self.addChildViewController(pageViewController!)
//self.view.addSubview(pageViewController!.view)
self.view.insertSubview(pageViewController!.view, at: 0)
pageViewController!.didMove(toParentViewController: self)
}
//Setup Pagination Icons and count
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return images.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
func setupPageControll(){
let apperance = UIPageControl.appearance()
apperance.pageIndicatorTintColor = UIColor.gray
apperance.currentPageIndicatorTintColor = UIColor.white
apperance.backgroundColor = UIColor.clear
}
func currentControllerIndex() -> Int{
let pageItemController = self.currentConroller()
if let controller = pageItemController as? ContentViewController {
return controller.itemIndex
}
return -1
}
///////////////////////////////////////////////
func currentConroller() -> UIViewController?{
if (self.pageViewController?.viewControllers?.count)! > 0{
return self.pageViewController?.viewControllers![0]
}
return nil
}
func getContentViewController(withIndex index: Int) -> ContentViewController? {
if index < images.count{
let contentVC = self.storyboard?.instantiateViewController(withIdentifier: "ContentViewController") as! ContentViewController
contentVC.itemIndex = index
contentVC.imageName = images[index]
return contentVC
}
return nil
}
}
extension PageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
pendingIndex = (pendingViewControllers.first as! ContentViewController).itemIndex
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
let currentIndex = pendingIndex
if let index = currentIndex {
self.PageControl.currentPage = index
}
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex > 0 {
return getContentViewController(withIndex: contentVC.itemIndex - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex + 1 < images.count {
return getContentViewController(withIndex: contentVC.itemIndex + 1)
}
return nil
}
}

Select your PageViewController on story board and set. Spine Location none to Mid. Also Check double sided.
Modify your code as below. (Changes done on your own code)
import UIKit
class PageViewController: UIViewController {
#IBOutlet weak var PageControl: UIPageControl!
var pageViewController: UIPageViewController?
var images = ["01","02","03","04"]
var pendingIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControll()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createPageViewController() {
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.isDoubleSided = true
pageController.dataSource = self
pageController.delegate = self
if images.count > 1{
let firstController = getContentViewController(withIndex: 0)!
let secondController = getContentViewController(withIndex: 1)!
let contentControllers = [firstController,secondController]
pageController.setViewControllers(contentControllers, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
pageViewController = pageController
self.addChildViewController(pageViewController!)
self.view.insertSubview(pageViewController!.view, at: 0)
pageViewController!.didMove(toParentViewController: self)
}
//Setup Pagination Icons and count
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return images.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
func setupPageControll(){
let apperance = UIPageControl.appearance()
apperance.pageIndicatorTintColor = UIColor.gray
apperance.currentPageIndicatorTintColor = UIColor.white
apperance.backgroundColor = UIColor.clear
}
func currentControllerIndex() -> Int{
let pageItemController = self.currentConroller()
if let controller = pageItemController as? ContentView {
return controller.itemIndex
}
return -1
}
///////////////////////////////////////////////
func currentConroller() -> UIViewController?{
if (self.pageViewController?.viewControllers?.count)! > 0{
return self.pageViewController?.viewControllers![0]
}
return nil
}
func getContentViewController(withIndex index: Int) -> ContentView? {
if index < images.count{
let contentVC = self.storyboard?.instantiateViewController(withIdentifier: "ContentViewController") as! ContentView
contentVC.itemIndex = index
//contentVC.imageName.image = self.images[index]
return contentVC
}
return nil
}
}
extension PageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
pendingIndex = (pendingViewControllers.first as! ContentView).itemIndex
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentView
if contentVC.itemIndex > 0 {
return getContentViewController(withIndex: contentVC.itemIndex - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentView
if contentVC.itemIndex + 1 < images.count {
return getContentViewController(withIndex: contentVC.itemIndex + 1)
}
return nil
}
}
Github Full Project.

Related

swift: UIPageViewController action

I have UIPageViewController and this code to flip my pages :
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex > 0 {
return getContentViewController(withIndex: contentVC.itemIndex - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex + 1 < images.count {
return getContentViewController(withIndex: contentVC.itemIndex + 1)
}
return nil
}
But I want to flip pages on button press. I should call viewControllerBefore and viewControllerAfter in my button action? Or I should write another code? How to do it?
Update
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControll()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func createPageViewController() {
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.dataSource = self
pageController.delegate = self
if images.count > 0{
let firstController = getContentViewController(withIndex: 0)!
let contentControllers = [firstController]
pageController.setViewControllers(contentControllers, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
pageViewController = pageController
self.addChildViewController(pageViewController!)
self.view.insertSubview(pageViewController!.view, at: 0)
pageViewController!.didMove(toParentViewController: self)
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return images.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
func setupPageControll(){
let apperance = UIPageControl.appearance()
apperance.pageIndicatorTintColor = UIColor.gray
apperance.currentPageIndicatorTintColor = UIColor.white
apperance.backgroundColor = UIColor.clear
}
func currentControllerIndex() -> Int{
let pageItemController = self.currentConroller()
if let controller = pageItemController as? ContentViewController {
return controller.itemIndex
}
return -1
}
func currentConroller() -> UIViewController?{
if (self.pageViewController?.viewControllers?.count)! > 0{
return self.pageViewController?.viewControllers![0]
}
return nil
}
func getContentViewController(withIndex index: Int) -> ContentViewController? {
if index < images.count{
let contentVC = self.storyboard?.instantiateViewController(withIdentifier: "ContentViewController") as! ContentViewController
contentVC.itemIndex = index
contentVC.imageName = images[index]
return contentVC
}
return nil
}
}
extension PageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
pendingIndex = (pendingViewControllers.first as! ContentViewController).itemIndex
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
let currentIndex = pendingIndex
if let index = currentIndex {
self.PageControl.currentPage = index
}
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex > 0 {
return getContentViewController(withIndex: contentVC.itemIndex - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex + 1 < images.count {
return getContentViewController(withIndex: contentVC.itemIndex + 1)
}
return nil
}
New Update
new:
#IBAction func nextAction(_ sender: Any) {
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.dataSource = self
pageController.delegate = self
let secondController = getContentViewController(withIndex: 1)!
let contentControllers = [secondController]
pageController.setViewControllers(contentControllers, direction: .forward, animated: true, completion: nil)
pageViewController = pageController
}
You need to use this instance method
setViewControllers(_ viewControllers: [UIViewController]?,
direction: UIPageViewController.NavigationDirection,
animated: Bool,
completion: ((Bool) -> Void)? = nil)
Like this
// self is of type UIPageViewController
self.setViewControllers([vc],direction:.forward,animated:true) { _ in
}
#IBAction func nextPageBtnPressed_TouchupInside(_ sender : UIButton ) {
if let pageViewController = self.parent as? PageViewController {
pageViewController.goToNextPage()
pageViewController.changeCurrentPageIndicator(pageViewController: pageViewController)
}
}
func goToNextPage(animated: Bool = true, completion: ((Bool) -> Void)? = nil) {
if let currentViewController = viewControllers?[0] {
if let nextPage = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) {
setViewControllers([nextPage], direction: .forward, animated: animated, completion: completion)
}
}
func changeCurrentPageIndicator(pageViewController : DTCPageViewController) {
pageViewController.view.clipsToBounds = false
pageViewController.view.sizeToFit()
let pageContentViewController = pageViewController.viewControllers![0]
currentIndex = orderViewController.index(of: pageContentViewController)!
self.pageControl.currentPage = orderViewController.index(of: pageContentViewController)!
}
write goToNextPage() and changeCurrentPageIndicator() ------
In PageViewControllerClass
Or make extension
extension PageViewController

How to Reset/reload the UI Page Controller views in swift [duplicate]

This question already has answers here:
Refresh UIPageViewController - reorder pages and add new pages
(4 answers)
Closed 4 years ago.
I am looking to how to reload the UI page controller.
On a table VC I have added UIHeaderView and embedded the UIPage VC.
Page VC is loading images dynamically from firebase.
First time it is loading the right set of images but when on the table VC I selecting other cel the Page VC need to refresh its data.
How to achieve this functionality
Here is the coed I have written for PAGE VC
//-----PAGE VC CODE------
import UIKit
import Firebase
protocol ProductImagesPageVCDelegate: class
{
func setupPageController(numberOfPages: Int)
func turnPageController(to index: Int)
}
class ProductImagesPageVC: UIPageViewController {
var product: Product!
weak var pageViewControllerDelegate: ProductImagesPageVCDelegate?
struct StoryBoard {
static let productImageVC = "ProductImageVC"
}
lazy var controllers: [UIViewController] = {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var controllers = [UIViewController]()
if let imageLinks = self.product.imageLinks
{
for imageLink in imageLinks
{
let productImageVC = storyboard.instantiateViewController(withIdentifier: StoryBoard.productImageVC)
controllers.append(productImageVC)
}
}
self.pageViewControllerDelegate?.setupPageController(numberOfPages: controllers.count)
return controllers
}()
override func viewDidLoad() {
super.viewDidLoad()
// if #available(iOS 11.0, *) {
// contentInsetAdjustmentBehavior = .never
// } else {
// automaticallyAdjustsScrollViewInsets = false
// }
automaticallyAdjustsScrollViewInsets = false
dataSource = self
delegate = self
self.turnToPage(index: 0)
}
func turnToPage(index: Int)
{
let controller = controllers[index]
var direction = UIPageViewControllerNavigationDirection.forward
if let currentVC = viewControllers?.first
{
guard let currentIndex = controllers.index(of: currentVC) else {return}
if currentIndex > index
{
direction = .reverse
}
}
self.configuewDisplaying(viewController: controller)
setViewControllers([controller], direction: direction, animated: true, completion: nil)
}
func configuewDisplaying(viewController: UIViewController)
{
for (index, vc) in controllers.enumerated()
{
if viewController === vc {
if let productImageVC = viewController as? ProductImageVC
{
productImageVC.imageLink = self.product.imageLinks?[index]
self.pageViewControllerDelegate?.turnPageController(to: index)
}
}
}
}
}
extension ProductImagesPageVC: UIPageViewControllerDataSource
{
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let index = controllers.index(of: viewController)
{
if index < controllers.count - 1
{
return controllers[index + 1]
}
}
return controllers.first
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let index = controllers.index(of: viewController)
{
if index > 0
{
return controllers[index - 1]
}
}
return controllers.last
}
}
extension ProductImagesPageVC: UIPageViewControllerDelegate
{
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
self.configuewDisplaying(viewController: pendingViewControllers.first as! ProductImageVC)
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if !completed
{
self.configuewDisplaying(viewController: previousViewControllers.first as! ProductImageVC)
}
}
}
Try this-
let viewControllers: [UIViewControllers] = [UIViewController()]
if let pageViewController = parentViewController as? UIPageViewController {
pageViewController.setViewControllers(viewControllers, direction: .Forward, animated: true, completion: nil)}

How do I hide the status bar on my UIPageViewController? (All view controllers)

I've searched every question/answer I can find on here, but I can't figure out how to hide the status bar for all of the view controllers in my UIPageViewController. Here's the code from my UIPageViewController class:
class TipsVC: UIPageViewController, UIPageViewControllerDelegate {
lazy var VCArr: [UIViewController] = {
return [self.VCInstance(name: "T1"),
self.VCInstance(name: "T2"),
self.VCInstance(name: "T3")]
}()
private func VCInstance(name: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)
}
override public func viewDidLoad() {
super.viewDidLoad()
//self.dataSource = self
self.delegate = self
if let OB1 = VCArr.first {
setViewControllers([OB1], direction: .forward, animated: true, completion: nil)
let pageController = UIPageControl.appearance()
pageController.pageIndicatorTintColor = UIColor(red:1.00, green:0.88, blue:0.92, alpha:1.0)
pageController.currentPageIndicatorTintColor = UIColor(red:1.00, green:0.25, blue:0.51, alpha:1.0)
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews {
if view is UIScrollView {
view.frame = UIScreen.main.bounds
} else if view is UIPageControl {
view.backgroundColor = UIColor.clear
}
}
}
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?{
guard let viewControllerIndex = VCArr.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return VCArr.last
}
guard VCArr.count > previousIndex else {
return nil
}
return VCArr[previousIndex]
}
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?{
guard let viewControllerIndex = VCArr.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
guard nextIndex < VCArr.count else {
return VCArr.first
}
guard VCArr.count > nextIndex else {
return nil
}
return VCArr[nextIndex]
}
public func presentationCount(for pageViewController: UIPageViewController) -> Int{
return VCArr.count
}
public func presentationIndex(for pageViewController: UIPageViewController) -> Int{
guard let OB1 = viewControllers?.first,
let OB1Index = VCArr.index(of: OB1) else {
return 0
}
return OB1Index
}
public func nextPageWithIndex(index: Int)
{
let nextVC = VCArr[index]
setViewControllers([nextVC], direction: .forward, animated: true, completion: nil)
}
}
and here's a code sample from one of my viewControllers:
class T1: UIViewController {
#IBOutlet var nextBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
UIApplication.shared.isStatusBarHidden = true
}
#IBAction func nextBtnDidPress(_ sender: Any) {
let next = self.parent as! TipsVC
next.nextPageWithIndex(index: 1)
}
}
I'm well aware of how to hide the status bar on regular view controllers, but I'm unable to get the same results when I'm using a UIPageViewController. What's going on?
To hide statusbar from particluar viewController you need to hide status bar in viewWillAppear and hide status bar in viewWillDisAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIApplication.shared.isStatusBarHidden = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
UIApplication.shared.isStatusBarHidden = false
}
viewWillAppear will call before opening particular viewController and viewWillDisAppear call after dismiss particular viewController
if you face problem with UIPageViewController use UIViewController and embed UIPageViewController inside that for reference check below code
var pageContainer: UIPageViewController!
pageContainer = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
pageContainer.delegate = self
pageContainer.dataSource = self
pageContainer.setViewControllers([getViewControllerAtIndex(index: 0)] as [UIViewController], direction: .forward, animated: false, completion: nil)
pageContainer.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.view.addSubview(pageContainer.view)
Hope this will help you

PageViewController - Auto Slide - Swift 3

I am trying to auto-slide the page view controller pages and the page indicator simultaneously. There are 5 pages in my page view controller. The flow works fine from pic 1-5, but I am unable to go back from 5th to 1st image and restart the auto sliding.
Below is my code:
import UIKit
class PageSliderViewController: UIViewController , UIPageViewControllerDataSource, UIPageViewControllerDelegate {
#IBOutlet weak var pageControl: UIPageControl!
var pageContainer: UIPageViewController!
// The pages it contains
var pages = [UIViewController]()
// Track the current index
var currentIndex: Int?
private var pendingIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
// Setup the pages
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let page1: UIViewController! = storyboard.instantiateViewController(withIdentifier: "Page1")
let page2: UIViewController! = storyboard.instantiateViewController(withIdentifier: "Page2")
let page3: UIViewController! = storyboard.instantiateViewController(withIdentifier: "Page3")
let page4: UIViewController! = storyboard.instantiateViewController(withIdentifier: "Page4")
let page5: UIViewController! = storyboard.instantiateViewController(withIdentifier: "Page5")
pages.append(page1)
pages.append(page2)
pages.append(page3)
pages.append(page4)
pages.append(page5)
// Create the page container
pageContainer = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
pageContainer.delegate = self
pageContainer.dataSource = self
pageContainer.setViewControllers([page1], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
currentIndex = 0
// Add it to the view
view.addSubview(pageContainer.view)
// Configure our custom pageControl
self.view.bringSubview(toFront: self.loginButton)
self.view.bringSubview(toFront: self.signUpButton)
self.view.bringSubview(toFront: self.pageControl)
pageControl.numberOfPages = pages.count
pageControl.currentPage = 0
Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.next(_:)),
userInfo: nil,
repeats: true)
}
func next(_ timer: Timer) {
pageContainer.goToNextPage()
currentIndex = currentIndex! + 1
if currentIndex == pageControl.numberOfPages{
currentIndex = 0
}
pageControl.currentPage = currentIndex!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - UIPageViewController delegates
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)!
if currentIndex == 0 {
return nil
}
let previousIndex = abs((currentIndex - 1) % pages.count)
return pages[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)!
if currentIndex == pages.count-1 {
return nil
}
let nextIndex = abs((currentIndex + 1) % pages.count)
return pages[nextIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
pendingIndex = pages.index(of: pendingViewControllers.first!)
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
currentIndex = pendingIndex
if let index = currentIndex {
pageControl.currentPage = index
}
}
}
}
extension UIPageViewController {
func goToNextPage(animated: Bool = true, completion: ((Bool) -> Void)? = nil) {
if let currentViewController = viewControllers?[0] {
if let nextPage = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) {
setViewControllers([nextPage], direction: .forward, animated: animated, completion: completion)
}
}
}
}
Note that through this code the page control goes from 5th to 1st dot but the page is not changing. There is some minor mistake but unable to figure it out. Any help would be greatly appreciated!
I haven't tried to run this code, but my guess is:
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)!
if currentIndex == pages.count-1 {
return nil
}
let nextIndex = abs((currentIndex + 1) % pages.count)
return pages[nextIndex]
}
Arrays are zero-based, so if you are currently looking at page5, you are looking at pages[4] ... and pages.count - 1 equals 4. So, your code is saying:
if the current page is page5
return nil
So your func goToNextPage() extension calls for viewControllerAfter and gets nil in return.
You most likely want to change viewControllerAfter to be:
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)!
// you don't need this, because you are using % modulo operator
// to keep "nextIndex" within the array bounds
//if currentIndex == pages.count-1 {
// return nil
//}
let nextIndex = abs((currentIndex + 1) % pages.count)
return pages[nextIndex]
}

Change specific page UiPageViewController

I have a Page view controller (see below), what i want to achieve is to go to the FirstVC from ThirdVC and only from that!! with a function or a button, can anyone help me?
Here you can see the code of my PageVC
import UIKit
class PageVC: UIPageViewController,UIPageViewControllerDataSource, UIPageViewControllerDelegate{
lazy var VCArr: [UIViewController] = {
return [self.VCInstance(name: "FirstVC"), self.VCInstance(name: "SecondVC"), self.VCInstance(name: "ThirdVC")]
}()
private func VCInstance(name: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle:nil).instantiateViewController(withIdentifier: name)
}
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
if let firstVC = VCArr.first {
setViewControllers([firstVC], direction: .forward, animated: true, completion: nil)
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews {
if view is UIScrollView {
view.frame = UIScreen.main.bounds
} else if view is UIPageControl {
view.backgroundColor = UIColor.clear
}
}
}
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = VCArr.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else{
return VCArr.last
}
guard VCArr.count > previousIndex else {
return nil
}
return VCArr[previousIndex]
}
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = VCArr.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
guard nextIndex < VCArr.count else{
return VCArr.first
}
guard VCArr.count > nextIndex else {
return nil
}
return VCArr[nextIndex]
}
public func presentationCount(for pageViewController: UIPageViewController) -> Int {
return VCArr.count
}
public func presentationIndex(for pageViewController: UIPageViewController) -> Int {
guard let firstViewController = viewControllers?.first, let firstViewControllerIndex = VCArr.index(of: firstViewController) else{
return 0
}
return firstViewControllerIndex
}
}
Ok i found a solution here:
How do I change the UIPageViewController from WITHIN one of the UIViewControllers that is part of the UIPageViewController?
Simply i added this function to PageVC:
func nextPageWithIndex(index: Int)
{
let nextWalkthroughVC = VCArr[index]
setViewControllers([nextWalkthroughVC], direction: .forward, animated: true, completion: nil)
}
Then in the ThirdVC view controller i added in my function:
let parent = self.parent as! PageVC
parent.nextPageWithIndex(index: 0)
Where 0 is the index of the view controller that i want to show
And works perfectly!

Resources