Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Call Function in PageViewController from other Viewcontroller

I got an PageViewController which loads two "child "ViewControllers in order to let the user "swipe" through them. I don't want this swipe gesture , but instead I want to have a function inside my ViewController which allows me to use setViewControllers in the PageViewController.

I tried using protocols but even that didn't work out.

I would realy appreciate any help or suggestions on how I could accomplish that. Thanks!

like image 257
Phil Legat Avatar asked Mar 10 '23 19:03

Phil Legat


1 Answers

To access setViewControllers from your child view controllers, you will need your child view controllers to be aware of their parent PageViewController. To do so, start by making a Protocol (I know you've said you've tried Protocols, but please please see my method through). This Protocol will ensure that every child view controller has a reference to the parent PageViewController.

    protocol PageObservation: class {
        func getParentPageViewController(parentRef: PageViewController)
    }

Ensure that your child view controllers adhere to the PageObservation Protocol.

    class Child1ViewController: UIViewController, PageObservation {
        var parentPageViewController: PageViewController!
        func getParentPageViewController(parentRef: PageViewController) {
            parentPageViewController = parentRef
        }
    }

    class Child2ViewController: UIViewController, PageObservation {
        var parentPageViewController: PageViewController!
        func getParentPageViewController(parentRef: PageViewController) {
            parentPageViewController = parentRef
        }
    }

In your PageViewController, as you create each child view controller, cast them to the PageObservation type and pass a reference of the parent PageViewController. I use an array called orderViewControllers to create my pages. My UIPageViewControllerDataSource delegate methods uses it to know which pages to load but that is irrelevant to this example, I just thought I'd let you know in case you have a different way of creating your pages.

    class PageViewController: UIPageViewController {
        var orderedViewControllers: [UIViewController] = []


        //creating child 1
        //i am using storyboard to create the child view controllers, I have given them the identifiers Child1ViewController and Child2ViewController respectively
        let child1ViewController =  UIStoryboard(name: "Main", bundle: nil) .
        instantiateViewController(withIdentifier: "Child1ViewController")
        let child1WithParent = child1ViewController as! PageObservation
        child1WithParent.getParentPageViewController(parentRef: self)

        orderedViewControllers.append(child1ViewController)

        //creating child 2
        let child2ViewController =  UIStoryboard(name: "Main", bundle: nil) .
        instantiateViewController(withIdentifier: "Child2ViewController")
        let child2WithParent = child2ViewController as! PageObservation
        child2WithParent.getParentPageViewController(parentRef: self)

        orderedViewControllers.append(child2ViewController)
    }

Now inside your child view controllers, you have access to setViewControllers. For example, if I want to call setViewControllers in the child1ViewController, I have created a func called accessSetViewControllers() where I access the setViewControllers:

    class Child1ViewController: UIViewController, PageObservation {
         var parentPageViewController: PageViewController!
        func getParentPageViewController(parentRef: PageViewController) {
            parentPageViewController = parentRef
        }

        func accessSetViewControllers() {
             parentPageViewController.setViewControllers( //do what you need )
        }
    }

On a side note, despite what other answers above have said, you can set dataSource to whatever you like. I sometimes set dataSource to nil to prevent the user from swiping away from a screen before doing something and then add the dataSource back to allow them to continue swiping.

like image 141
gwinyai Avatar answered Apr 06 '23 01:04

gwinyai