5

I'm trying to change the current ViewController of my UIPageViewController using a NEXT button. So I'm calling the function that's in my containterViewController in my mainViewController using a delegate. But it doesn't execute the setViewControllers line.

Here you can see my code:

This is the method that I call using my delegate:

func forwardPage() {
    print("Start")
    currentPage += 1
    print(vcs[currentPage])
    self.setViewControllers([vcs[currentPage]], direction: .forward, animated: true) { (true) in
        print("Done")
    }
}

Here's my delegate:

protocol WalkthroughViewControllerDelegate {
   func forwardPage()
   func currentIndex() -> Int
}

And here's the function that is connected to my NEXT button:

@IBAction func nextButtonTapped(_ sender: Any) {
    if let index = delegate?.currentIndex() {
        print("Here... \(index)")
        switch index {
        case 0...1:
            print("Forwarding...")
            delegate?.forwardPage()
        case 2:
            dismiss(animated: true, completion: nil)
        default: break
        }
    }

    updateUI()
}

Everything but the "Done" gets printed

I would really appreciate your help

I've been struggling because of this for quite some time now

Thank you very much :)

EDIT: Maybe this happens because that UIPageViewController is inside a containerView. But I'm not sure

SECOND EDIT: I've created a git-hub repository just for this issue. Here's the link: https://github.com/LennartPhil/App-Popup-Screen. I hope you can understand that I won't show you all of my files.

Lennart P.
  • 316
  • 1
  • 6
  • 20
  • *"I'm calling the function that's in my containterViewController"* ... Is `forwardPage()` in your `UIPageViewController` class? In other words, is `self` there an instance of `UIPageViewController`? – DonMag Apr 24 '18 at 19:40
  • And... I did my test with a page view controller embedded in a containerView, so that's not the issue (unless you're func is in the wrong place). – DonMag Apr 24 '18 at 19:49
  • Yes, `self` is of type `UIPageViewController` – Lennart P. Apr 25 '18 at 13:34
  • Hmm... not sure then why your code is not working. Have you stepped through it to inspect your vars? I have a simple example project that uses an embedded Page View Controller, along with buttons to programmatically change pages... and the trailing completion block *does* get called. You can take a look, and compare my approach to yours to see if anything jumps out: https://github.com/DonMag/EmbeddedPageView – DonMag Apr 25 '18 at 14:19
  • Thank you so much for your help. Unfortunately, I can't really find anything that could help me. But thx anyways, I really appreciate it a lot :) – Lennart P. Apr 25 '18 at 16:15
  • Well, another thought... your initial question said *"it doesn't execute the setViewControllers line"* ... Does that mean your page doesn't change? Or it changes, but "Done" doesn't get printed to the console? – DonMag Apr 25 '18 at 16:33
  • The page doesn't change and "Done" doesn't get printed, so both – Lennart P. Apr 28 '18 at 08:40
  • OK - if your "page" doesn't change, it sounds like you indexing is off, and you are calling `setViewControllers` with the currently displayed VC (and the completion doesn't get called because you didn't actually change the VC). Try changing `currentPage += 1` to `currentPage = self.currentIndex() + 1` and see if that changes the page. – DonMag Apr 30 '18 at 12:51
  • Unfortunately, the result didn't change: I can swipe through the different ViewControllers but once I press the NextButton nothing happens. But I really appreciate how devoted you are to solving my problem. Thank you so much :) – Lennart P. Apr 30 '18 at 19:46
  • I expect you need to look closely at your indexing. Even if the page isn't visually changing, your code *appears* to be incrementing a `currentPage` variable. So, if you tap next, next, next, does your `currentIndex()` func return 0, 1, 2? – DonMag Apr 30 '18 at 20:24
  • The weird thing is that the index is correct. I print out the index and it's the right one, that's why I am so confused. And yes the `currentIndex()` function does return 0, 1, 2 – Lennart P. May 01 '18 at 10:46
  • Have you looked at copying another example of the setViewControllers method? - [how about this one](https://stackoverflow.com/questions/7208871/is-it-possible-to-turn-page-programmatically-in-uipageviewcontroller) – Wez May 01 '18 at 11:11
  • @LennartP. Did you see `self.setViewControllers` is an asynchronous call and you're updating the UI just after this? `updateUI()` will be call before printing the "Done" so you should update the UI somehow inside this completion block. – TheTiger May 01 '18 at 11:34
  • @LennartP. -- I think you need to show a bit more of your code. You must be doing *something* else that's preventing the "page change". I modified my sample app (that I linked to above) to use a delegate pattern as you're using, and still have no problem - it shows the next page as desired. And just to be clear... your `forwardPage()` func *is* being executed? You get "Start" printed to the console? If so, add a `print(self.viewControllers)` immediately before `print(vcs[currentPage])` and make sure it's not the same VC. – DonMag May 01 '18 at 12:45
  • Are you using this example? https://github.com/n6xej/CSWXIBWalkThrough – Dimple Shah May 01 '18 at 12:57
  • @LennartP. -- and... what's going on in `updateUI()`? Are you inadvertently setting the current page back to the one you just tried to change? – DonMag May 01 '18 at 13:43
  • Can you take a snapshot of your view hierarchy and paste it? – Arun Balakrishnan May 01 '18 at 18:05
  • are there any compiler warnings? for example: { (true) in print("Done") } should be: { _ in print("Done") } – Aaron Halvorsen May 01 '18 at 20:27
  • How are you setting the delegate(pageViewController) of the container view? – Santhosh R May 01 '18 at 20:51
  • I added a link to all the files so you can check them out if you want to. Don't worry, there are just two main files – Lennart P. May 02 '18 at 18:31

1 Answers1

2

OK - the problem is that your code in viewDidLoad():

    let storyboard = UIStoryboard(name: "ExtraViewControllers", bundle: nil)
    let walkthroughPageVC = storyboard.instantiateViewController(withIdentifier: "WalkthroughPageVC") as! WalkthroughPageViewController
    delegate = walkthroughPageVC

is creating a NEW instance of WalkthroughPageViewController, which goes out of scope as soon as viewDidLoad() exits. So it no longer exists.

What you need to do instead is get a reference to it in prepare(for segue:...), and set it as your delegate there:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let vc = segue.destination as? WalkthroughPageViewController {
        self.delegate = vc
    }
}

I forked your GitHub repo and added the files into a project, so you can see it run: https://github.com/DonMag/App-Popup-Screen

DonMag
  • 69,424
  • 5
  • 50
  • 86