Swift: UIPageViewController: carga vistas separadas

Estoy siguiendo este tutorial: http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/ para crear una aplicación que muestre varios controles deslizantes.

Aunque tengo este tutorial para trabajar, este ejemplo solo cambia una image basada en las que están almacenadas en una matriz.

¿Cómo puedo conseguir cargar ViewControllers en lugar de imágenes?

Tengo 4 ViewControllers:

  • ViewController1
  • ViewController2
  • ViewController3
  • ViewController4

Me gustaría deslizar uno para mostrar ViewController1 y slide2 para cargar ViewController2, etc.

Aquí está mi ViewController principal:

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 } 

y aquí está mi 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) } } 

Soy nuevo en Swift / iOS Development y realmente trato de desarrollarlo. Gracias de antemano por sus respuestas 🙂

EDITAR: hacer que la pregunta sea clara

¿Cómo hago para que haya una matriz de controlleres de vista que corresponda a la diapositiva izquierda / derecha del UIPageViewController?

Entonces, cuando deslizo a la izquierda en ViewController1, el UIViewController2 está cargado e invertido para deslizar hacia la derecha.

Suponiendo que tiene los controlleres de vista 1-4 definidos en el mismo guión gráfico que su UIPageViewController, y tiene sus ID de Guiones charts configurados como ViewController0, ViewController1 y, por lo tanto, cree un método para rellenar su matriz de controller de vista y llamarlo en su viewDidLoad() antes de llamar a createPageViewController()

  override func viewDidLoad() { super.viewDidLoad() populateControllersArray() createPageViewController() setupPageControl() } 

Implementar el método así:

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

Y defina su createPageViewController() como el siguiente

  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) } 

luego en sus dos methods de antes y después de delegates:

  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 } 

Y en el método de conteo

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

De hecho, puede rellenar controllers con cualquier controller de vista que desee mostrar, simplemente configure su class como PageItemController en el guión gráfico (para tener una propiedad de índice).

O puede configurar cada controller de vista como su propia class, y usar la obtención y configuration de la propiedad de time de ejecución.

Use controller.valueForKey("itemIndex") as Int en el método de antes y después en lugar de controller.itemIndex

Use controller.setValue(i, forKey: "itemIndex") lugar de controller.itemIndex = i en populateControllersArray() .

Solo asegúrese de que cada class de controller tenga la propiedad Int itemIndex , o su aplicación se cuelgue.

Para reunir todo en su código, haga lo siguiente:

 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 } 

Usted carga ViewControllers para cada página. cada image que muestre está dentro de ViewController. Eso se hace a través de:

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

si cada página tuya usa el mismo layout, no hay nada que hacer aquí, excepto diseñar este ViewController en el Interface Builder. Sin embargo, si cada página usa un layout diferente y muestra diferentes datos, primero prototypes / layout de los ViewControllers en Interface Builder.

entonces creará classs para cada ViewController y las extenderá desde PageItemController. Solo mantiene la variable de índice en PageItemController y mueve el rest de su lógica a las subclasss.

 import UIKit class PageItemController: UIViewController { // MARK: - Variables var itemIndex: Int = 0 } 

por ejemplo, un viewController que contiene una image

 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) } } 

finalmente, simplemente cambia la function getItemController para devolver el ViewController correcto para el índice especificado. aquí usted pasa datos al ViewController o simplemente lo devuelve.

 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 } 

Aquí hay un excelente repago para esto:

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) } 

Obtuve el código de Eric Ferreira para trabajar (Xcode 6.4). Quería usar un controller de vista de página para mostrar dos controlleres de vista completamente únicos con tags que muestran diferentes datos de una database de Realm.

Lo puse a trabajar en un proyecto de testing donde usé 2 storyboards, cada uno con una sola label que está establecida por su propia class que contiene el IBOutlet en la label y el código que establece el text de la label, esto simula adecuadamente la forma en que muestro mi Datos de la database del reino. Cada class de storyboard henetworkinga el PageItemController para tener disponible la variable "itemIndex". The PageItemController en turnos henetworkinga UIViewController completando la cadena de inheritance.

Espero que esto ayude a alguien que está tratando de utilizar storyboards completamente únicos.