Using UIPageViewController with swift and multiple view controllers

旧城冷巷雨未停 提交于 2019-12-17 10:24:32

问题


I'm trying to utilize a UIPageViewController in a Swift app with multiple view controllers. I have 2 view controllers on my storyboard (firstViewController and secondViewController) that are both embedded in their own navigation controllers. They have storyboard identifiers "FirstViewController" and "SecondViewController". I also have a page view controller on my storyboard with identifierPageView controller and set the navigation to horizontal and transition style to scroll in the attributes inspector. FirstViewController is the root view controller of the app

I want firstViewController to be the first page of the page view controller so I have written its class like so:

import Foundation
import UIKit

class FirsttViewController: UITableViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate  {

    override func viewDidLoad() {

        let pageViewController: PageViewController = self.storyboard.instantiateViewControllerWithIdentifier("PageViewController") as PageViewController

        pageViewController.delegate = self

        var viewControllers: [UIViewController] = [self]

        pageViewController.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
        pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)

        self.addChildViewController(pageViewController)
        self.view.addSubview(pageViewController.view)
        pageViewController.didMoveToParentViewController(self)


    }
    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {


        let secondViewController: SecondViewController = self.storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as SecondViewController


        return secondViewController
    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        return nil
    }

    func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 2
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 0
    }
}

the file for SecondViewController looks like this:

import Foundation
import UIKit

class SecondViewController: UITableViewController, UIPageViewControllerDataSource {

    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {

        return nil
    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        let firstViewController: FirstViewController = self.storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController
        return firstViewController
    }

}

However, when I run my app it doesn't seem to have a page view controller. It just shows firstViewController and that's it. No dots, no pages, etc. Anyone know whats wrong? I've found a couple of Objective-C tutorials but they all cover using one view controller for all the pages and have a root view controller that is not a page in the pageView so they weren't too much help. I was hoping it was going to be like using a tabBarController where you just click and drag to the view controllers but thats not the case unfortunately. like I said I've not worked with one of these before so I'm sort of lost.

update:

following iiFreeman's suggestion, I subclassed UIPageViewController and made it the root in my storyboard file. below is the subclass

import Foundation
import UIKit
class PageViewController: UIPageViewController {

    override func viewDidLoad() {

        let startingViewController = self.storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController

        self.dataSource = startingViewController
        var viewControllers: [UIViewController] = [startingViewController]

        self.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)



    }

}

However now the app just hangs on a black screen and eventually Xcode loses connection to the simulator. I'm not really sure what's up.


回答1:


OK, I got it figured out. since I needed the page view controller to be the root and handle everything, I subclassed UIPageViewControlleras iiFreeman suggested and conformed to the delegate and data source protocols. I then set up the controller in viewDidLoad, and implemented the delegate and data source methods. I added a property store an array of storyboard identifiers as well as one to keep track of the current index of that array. I also added a helper method to return the correct view controller given an index. I didn't need anything in my other tableView controller subclasses since my page view controller was handling everything. One thing I did realize is since my tableViewControllers were embedded in navigation controllers, my page view controller actually needed to show the navigation controllers, not the tableView controllers. below is my implementation:

import Foundation
import UIKit

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    var index = 0
    var identifiers: NSArray = ["FirstNavigationController", "SecondNavigationController"]
    override func viewDidLoad() {

        self.dataSource = self
        self.delegate = self

        let startingViewController = self.viewControllerAtIndex(self.index)
        let viewControllers: NSArray = [startingViewController]
        self.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)



    }

    func viewControllerAtIndex(index: Int) -> UINavigationController! {

        //first view controller = firstViewControllers navigation controller
        if index == 0 {

            return self.storyboard.instantiateViewControllerWithIdentifier("FirstNavigationController") as UINavigationController

        }

        //second view controller = secondViewController's navigation controller
        if index == 1 {

            return self.storyboard.instantiateViewControllerWithIdentifier("SecondNavigationController") as UINavigationController
        }

        return nil
    }
    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {

        let identifier = viewController.restorationIdentifier
        let index = self.identifiers.indexOfObject(identifier)

        //if the index is the end of the array, return nil since we dont want a view controller after the last one
        if index == identifiers.count - 1 {

            return nil
        }

        //increment the index to get the viewController after the current index
        self.index = self.index + 1
        return self.viewControllerAtIndex(self.index)

    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        let identifier = viewController.restorationIdentifier
        let index = self.identifiers.indexOfObject(identifier)

        //if the index is 0, return nil since we dont want a view controller before the first one
        if index == 0 {

            return nil
        }

        //decrement the index to get the viewController before the current one
        self.index = self.index - 1
        return self.viewControllerAtIndex(self.index)

    }


    func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return self.identifiers.count
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 0
    }

}

this post helped me out a lot




回答2:


sure cause FirstViewController - initial view controller in your storyboard

add a custom UIPageViewController subclass into your storyboard, mark it as initial and do all work inside, instantiate page controller members by storyboardIDs in your UIPageViewController subclass, do the same thing just inside another class




回答3:


Please be aware that this code will only work with two ViewController. If you are planning on using more you have to change the line:

self.index = self.index + 1

Found at the before and after call, to:

self.index = index + 1

To call the current ViewController index.



来源:https://stackoverflow.com/questions/25387436/using-uipageviewcontroller-with-swift-and-multiple-view-controllers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!