1
votes

So I've been trying out UIPageViewController, where I have three different View Controllers (3 different classes)

So I've made it work! I can swipe from View Controller to View Controller, perfectly! At viewDidLoad of those three classes, I've made their self.view.tag = 0,1,2 respectively, so I know which my current View Controller is. Here's my RootViewController's code:

import UIKit

class ViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
@IBOutlet var bottomView: UIView!

var pageViewController: UIPageViewController!
var currentVCId = 0

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    pageViewController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
    pageViewController.dataSource = self
    pageViewController.delegate = self

    let starterVC = viewControllerWith(id: 0)

    pageViewController.setViewControllers([starterVC], direction: .forward, animated: false, completion: nil)
    pageViewController.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)

    self.addChildViewController(pageViewController)
    self.view.addSubview(pageViewController.view)
    self.view.bringSubview(toFront: bottomView)

    pageViewController.didMove(toParentViewController: self)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func viewControllerWith(id: Int) -> UIViewController {
    if id == 0 {
        return self.storyboard?.instantiateViewController(withIdentifier: "FirstPageContentViewController") as! FirstPageContentViewController
    }
    else if id == 1 {
        return self.storyboard?.instantiateViewController(withIdentifier: "SecondPageContentViewController") as! SecondPageContentViewController
    }
    else {
        return self.storyboard?.instantiateViewController(withIdentifier: "RandomColorViewController") as! RandomColorViewController
    }
}

func getViewControllerIdFor(previousViewController: Bool) -> Int? {
    if previousViewController == true {
        return currentVCId == 0 ? nil : currentVCId - 1
    }

    return currentVCId == 2 ? nil : currentVCId + 1
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
    if let returnIdValue = getViewControllerIdFor(previousViewController: true) {
        return viewControllerWith(id: returnIdValue)
    }

    return nil
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
    if let returnIdValue = getViewControllerIdFor(previousViewController: false) {
        return viewControllerWith(id: returnIdValue)
    }

    return nil
}

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    guard completed else {
        return
    }

    let viewController = pageViewController.viewControllers![0]
    currentVCId = viewController.view.tag
}

@IBAction func goToA(_ sender: UIButton) {
    if currentVCId != 0 {
        let currentVC = pageViewController.viewControllers?[0]
        let previusVC = pageViewController(pageViewController, viewControllerBefore: currentVC!)

        pageViewController.setViewControllers([previusVC!], direction: .reverse, animated: true, completion: nil)
        currentVCId = 0
    }
}

}

The thing is, I've added 2 buttons to my RootViewController, to switch from View Controller to View Controller without swiping.. So, let's assume that I have already swiped to the second View Controller and I want to go back to my first one, by pressing the left button.. Remember that my first VC has already been loaded, so I can have modified its content..

So now, if I press the button, its code is the last method above, it will navigate back, but it will create a new instance of the desired VC! What I want to do, is to show my already loaded VC, as if I swiped... Like Snapchat...

Any idea on how to achieve that?

1
just use method that is called when you swipeLu_
@Lu_ If you look at my code, you'll see that that's what I'm doing...Sotiris Kaniras
Show your before and after Page View Controller delegate methodBista

1 Answers

1
votes

This is from the documentation on instantiateViewController(withIdentifier:)

This method creates a new instance of the specified view controller each time you call it.

Which is why you are getting new instances. I would recommend a different approach. Instead of letting the pageViewController keep track of the VCs and accessing them blindly by index and tag, why not store them as a property in your root? This would allow you to ensure the same instance of the VC, and would let you get away from checking for tags (which is dirty) to something more readable like checking for equality with the actual VC object.