web-dev-qa-db-fra.com

Swift: UIPageViewController - Charge des vues séparées

Je suis ce tutoriel: http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/ pour créer une application affichant plusieurs curseurs. 

Même si ce tutoriel fonctionne, cet exemple ne modifie qu'une image en fonction de celles stockées dans un tableau. 

Comment puis-je le faire pour charger ViewControllers au lieu d'images

J'ai 4 ViewControllers:

  • ViewController1
  • ViewController2
  • ViewController3
  • ViewController4

Je voudrais que la diapositive 1 montre ViewController1 et la diapositive 2 pour charger ViewController2, etc.

Voici mon 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
}

et voici mon 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)
}
}

Je découvre le développement Swift/iOS et j'essaie vraiment de le développer en le développant. Merci d'avance pour vos réponses :)

EDIT: Pour clarifier la question

Comment faire pour qu'il y ait un tableau de contrôleurs de vue correspondant à la diapositive gauche/droite de UIPageViewController? 

Ainsi, lorsque je balaie à gauche sur ViewController1 - UIViewController2 est chargé et inversé pour balayer à droite. 

14
DannieCoderBoi

En supposant que les contrôleurs de vue 1 à 4 soient définis dans le même storyboard que votre UIPageViewController et que leurs ID de storyboard soient définis comme ViewController0, ViewController1, etc., créez une méthode pour renseigner votre tableau de contrôleurs de vue et appelez-le dans votre viewDidLoad() avant appelant createPageViewController()

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

Implémentez la méthode comme suit:

    var controllers = [PageItemController]()

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

Et définissez votre createPageViewController() comme suit

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

puis dans vos deux méthodes délégué avant et après:

    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
    }

Et dans la méthode de comptage

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

En fait, vous pouvez remplir controllers avec tous les contrôleurs de vue que vous souhaitez afficher. Il suffit de définir leur classe en tant que PageItemController dans le storyboard (afin de disposer de la propriété index).

Vous pouvez également définir chaque contrôleur de vue comme étant sa propre classe et utiliser les propriétés d’exécution et d’exécution.

Utilisez controller.valueForKey("itemIndex") as Int dans les méthodes before et after au lieu de controller.itemIndex 

Utilisez controller.setValue(i, forKey: "itemIndex") au lieu de controller.itemIndex = i dans populateControllersArray().

Assurez-vous simplement que chaque classe de contrôleur possède la propriété Int, itemIndex, sinon votre application se bloquera.

Pour tout rassembler dans votre code, procédez comme suit:

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
}
10
Eric F.

Vous chargez ViewControllers pour chaque page. chaque image que vous montrez se trouve dans son propre ViewController. Cela se fait par:

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

si chaque page de la vôtre utilise la même présentation, il ne reste plus rien à faire ici, à part la conception de ce ViewController dans Interface Builder . Si, toutefois, chaque page utilise une présentation différente et affiche des données différentes, vous devez d'abord créer un prototype concevoir ces ViewControllers dans Interface Builder.

vous créeriez alors des classes pour chaque ViewController et les étendriez à partir de PageItemController. Vous ne gardez que la variable d'index dans PageItemController et déplacez le reste de votre logique vers les sous-classes.

import UIKit

class PageItemController: UIViewController {

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

par exemple un viewController qui contient une 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)
    }
}

enfin, il vous suffit de modifier votre fonction getItemController pour renvoyer le ViewController correct pour l'index spécifié. Ici, vous transmettez des données à ViewController ou vous les renvoyez.

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
ergoon

Voici un excellent rapport pour cela:

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

Le code d'Eric Ferreira ci-dessus fonctionne (Xcode 6.4). Je souhaitais utiliser un contrôleur de vue de page pour afficher deux contrôleurs de vue totalement uniques avec des étiquettes affichant différentes données d'une base de données Realm. 

Je l’ai fait fonctionner dans un projet de test où j’ai utilisé 2 story-boards, chacun contenant une seule étiquette définie par sa propre classe contenant l’IBOutlet de l’étiquette et le code définissant le texte de l’étiquette. Données de base de données de royaume. Chaque classe de storyboard hérite de PageItemController afin de disposer de la variable "itemIndex". PageItemController hérite à son tour de UIViewController complétant la chaîne d'héritage.

J'espère que cela aidera quelqu'un qui cherche à utiliser des storyboards totalement uniques.

0
Delete My Account