Swift:UIPageViewController - 加载单独的视图

时间:2015-02-09 02:43:52

标签: ios swift uipageviewcontroller

我正在关注本教程:http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/创建一个显示多个滑块的应用。

尽管我已经开始使用本教程,但此示例仅根据存储在数组中的图像更改图像。

如何让它加载ViewControllers而不是图像

我有4个ViewControllers:

  • ViewController1
  • ViewController2
  • ViewController3
  • ViewController4

我想幻灯片一个显示ViewController1和slide2来加载ViewController2等....

这是我的主要ViewController:

 import UIKit

class ViewController: UIViewController, UIPageViewControllerDataSource {

// MARK: - Variables
private var pageViewController: UIPageViewController?

// Initialize it right away here
private let contentImages = ["nature_pic_1.png",
                             "nature_pic_2.png",
                             "nature_pic_3.png",
                             "nature_pic_4.png"];

// MARK: - View Lifecycle
override func viewDidLoad() {
    super.viewDidLoad()
    createPageViewController()
    setupPageControl()
}

private func createPageViewController() {

    let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
    pageController.dataSource = self

    if contentImages.count > 0 {
        let firstController = getItemController(0)!
        let startingViewControllers: NSArray = [firstController]
        pageController.setViewControllers(startingViewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
    }

    pageViewController = pageController
    addChildViewController(pageViewController!)
    self.view.addSubview(pageViewController!.view)
    pageViewController!.didMoveToParentViewController(self)
}

private func setupPageControl() {
    let appearance = UIPageControl.appearance()
    appearance.pageIndicatorTintColor = UIColor.grayColor()
    appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
    appearance.backgroundColor = UIColor.darkGrayColor()
}

// MARK: - UIPageViewControllerDataSource

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

    let itemController = viewController as PageItemController

    if itemController.itemIndex > 0 {
        return getItemController(itemController.itemIndex-1)
    }

    return nil
}

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

    let itemController = viewController as PageItemController

    if itemController.itemIndex+1 < contentImages.count {
        return getItemController(itemController.itemIndex+1)
    }

    return nil
}

private func getItemController(itemIndex: Int) -> PageItemController? {

    if itemIndex < contentImages.count {
        let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("ItemController") as PageItemController
        pageItemController.itemIndex = itemIndex
        pageItemController.imageName = contentImages[itemIndex]
        return pageItemController
    }

    return nil
}

// MARK: - Page Indicator

func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
    return contentImages.count
}

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

这是我的PageItemController:

import UIKit

class PageItemController: UIViewController {

// MARK: - Variables
var itemIndex: Int = 0
var imageName: String = "" {

    didSet {

        if let imageView = contentImageView {
            imageView.image = UIImage(named: imageName)
        }

    }
}

@IBOutlet var contentImageView: UIImageView?

// MARK: - View Lifecycle
override func viewDidLoad() {
    super.viewDidLoad()
    contentImageView!.image = UIImage(named: imageName)
}
}

我是Swift / iOS开发的新手,并且正在尝试通过开发进入它。提前感谢您的答案:)

编辑:使问题清晰

如何制作一个视图控制器数组,对应UIPageViewController的左/右滑动?

因此,当我在ViewController1上向左滑动时 - 加载UIViewController2并向右滑动以反向滑动。

4 个答案:

答案 0 :(得分:10)

假设您在与UIPageViewController相同的故事板中定义了视图控制器1-4,并且您将其Storyboard ID设置为ViewController0,ViewController1等,然后创建一个方法来填充视图控制器阵列并将其调用在致电viewDidLoad()

之前,您的createPageViewController()
    override func viewDidLoad() {
        super.viewDidLoad()
        populateControllersArray()
        createPageViewController()
        setupPageControl()
    }

实现如下方法:

    var controllers = [PageItemController]()

    func populateControllersArray() {
        for i in 0...3 {
            let controller = storyboard!.instantiateViewControllerWithIdentifier("ViewController\(i)") as PageItemController
            controller.itemIndex = i
            controllers.append(controller)
        }
    }

并将您的createPageViewController()定义为以下

    private func createPageViewController() {

        let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
        pageController.dataSource = self

        if !controllers.isEmpty {
            pageController.setViewControllers([controllers[0]], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
        }

        pageViewController = pageController
        addChildViewController(pageViewController!)
        self.view.addSubview(pageViewController!.view)
        pageViewController!.didMoveToParentViewController(self)
    }

然后在你的两个代表之前和之后的方法:

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        if let controller = viewController as? PageItemController {
            if controller.itemIndex > 0 {
                return controllers[controller.itemIndex - 1]
            }
        }
        return nil
    }
    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        if let controller = viewController as? PageItemController {
            if controller.itemIndex < controllers.count - 1 {
                return controllers[controller.itemIndex + 1]
            }
        }
        return nil
    }

在计数方法

    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return controllers.count
    }

实际上,您可以使用要显示的任何视图控制器填充controllers,只需将其类设置为storyboard中的PageItemController(以便具有索引属性)。

或者您可以将每个视图控制器设置为它自己的类,并使用运行时属性获取和设置。

在之前和之后的方法中使用controller.valueForKey("itemIndex") as Int而不是controller.itemIndex

controller.setValue(i, forKey: "itemIndex")中使用controller.itemIndex = i代替populateControllersArray()

确保每个控制器类都具有Int属性itemIndex,否则您的应用程序将崩溃。

要在代码中将所有内容整合在一起,请执行以下操作:

import UIKit

import UIKit

class ViewController: UIViewController, UIPageViewControllerDataSource {

    // MARK: - Variables
    private var pageViewController: UIPageViewController?

    // MARK: - View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        populateControllersArray()
        createPageViewController()
        setupPageControl()
    }

    var controllers = [PageItemController]()


    func populateControllersArray() {
        for i in 0...3 {
            let controller = storyboard!.instantiateViewControllerWithIdentifier("ViewController\(i)") as PageItemController
            controller.itemIndex = i
            controllers.append(controller)
        }
    }

    private func createPageViewController() {

        let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
        pageController.dataSource = self

        if !controllers.isEmpty {
            pageController.setViewControllers([controllers[0]], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
        }

        pageViewController = pageController
        addChildViewController(pageViewController!)
        self.view.addSubview(pageViewController!.view)
        pageViewController!.didMoveToParentViewController(self)
    }

    private func setupPageControl() {
        let appearance = UIPageControl.appearance()
        appearance.pageIndicatorTintColor = UIColor.grayColor()
        appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
        appearance.backgroundColor = UIColor.darkGrayColor()
    }

    // MARK: - UIPageViewControllerDataSource
    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        if let controller = viewController as? PageItemController {
            if controller.itemIndex > 0 {
                return controllers[controller.itemIndex - 1]
            }
        }
        return nil
    }
    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        if let controller = viewController as? PageItemController {
            if controller.itemIndex < controllers.count - 1 {
                return controllers[controller.itemIndex + 1]
            }
        }
        return nil
    }

    // MARK: - Page Indicator

    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return controllers.count
    }

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

答案 1 :(得分:2)

您确实为每个页面加载了ViewControllers。您展示的每个图像都在它自己的ViewController中。这是通过以下方式完成的:

private func getItemController(itemIndex: Int) -> PageItemController?

如果你的每一页都使用相同的布局,那么除了在Interface Builder中设计这个ViewController之外,这里没有什么可做的。 但是,如果每个页面使用不同的布局并显示不同的数据,那么首先要在Interface Builder中对这些ViewControllers进行原型设计。

然后你将为每个ViewController创建类并从PageItemController扩展它们。您只将索引变量保留在PageItemController中,并将其余逻辑移动到子类。

import UIKit

class PageItemController: UIViewController {

    // MARK: - Variables
    var itemIndex: Int = 0
}

例如一个包含图像的viewController

import UIKit

class PageImageViewController: PageItemController {
    // MARK: - Outlets
    @IBOutlet var contentImageView: UIImageView?

    // MARK: - Variables
    var imageName: String = "" {
        didSet {
            if let imageView = contentImageView {
                imageView.image = UIImage(named: imageName)
            }
        }
    }

    // MARK: - View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        contentImageView!.image = UIImage(named: imageName)
    }
}

最后,您只需更改getItemController函数,即可返回指定索引的正确ViewController。在这里,您可以将数据传递给ViewController,也可以将其返回。

private func getItemController(itemIndex: Int) -> UIViewController? {
    var vc: PageItemController? = nil

    switch itemIndex {
    case 0:
        // show an ImageViewController and pass data if needed
        vc = self.storyboard!.instantiateViewControllerWithIdentifier("ImageController") as PageImageViewController

        vc.itemIndex = itemIndex
        vc.imageName = "any_image_file"
    case 1:
        // show any other ViewController and pass data if needed
        vc = self.storyboard!.instantiateViewControllerWithIdentifier("ANY_OTHERController") as ANY_OTHERController

        vc.PRESENTABLE_DATA = ANY_PRESENTABLE_DATA_SOURCE
        vc.itemIndex = itemIndex
    case 2:
        // show any other ViewController and pass data if needed
        vc = self.storyboard!.instantiateViewControllerWithIdentifier("ANY_OTHERController") as ANY_OTHERController

        vc.PRESENTABLE_DATA = ANY_PRESENTABLE_DATA_SOURCE
        vc.itemIndex = itemIndex
    }

    return vc
}

答案 2 :(得分:1)

这是一个很棒的回购:

https://github.com/goktugyil/EZSwipeController

private func setupPageViewController() {
    pageViewController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.Scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: nil)
    pageViewController.dataSource = self
    pageViewController.delegate = self
    pageViewController.setViewControllers([stackPageVC[stackStartLocation]], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
    pageViewController.view.frame = CGRect(x: 0, y: Constants.StatusBarHeight, width: Constants.ScreenWidth, height: Constants.ScreenHeightWithoutStatusBar)
    pageViewController.view.backgroundColor = UIColor.clearColor()
    addChildViewController(pageViewController)
    view.addSubview(pageViewController.view)
    pageViewController.didMoveToParentViewController(self)
}

答案 3 :(得分:0)

我让Eric Ferreira的代码在上面工作(Xcode 6.4)。我想使用页面视图控制器来显示两个完全独特的视图控制器,其标签显示来自Realm数据库的不同数据。

我让它在一个测试项目中工作,我使用了两个故事板,每个故事板都包含一个由其自己的类设置的标签,其中包含标签的IBOutlet和设置标签文本的代码 - 这充分模拟了我的方式我正在显示我的Realm数据库数据。每个storyboard类都继承PageItemController,以便为其提供“itemIndex”变量。 PageItemController依次继承UIViewController来完成继承链。

我希望这可以帮助那些寻求使用完全独特的故事板的人。