web-dev-qa-db-ja.com

Swift:UIPageViewController-個別のビューを読み込む

私はこのチュートリアルに従っています: http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/ 複数のスライダーを表示するアプリを作成します。

このチュートリアルは機能していますが、この例では、配列に格納されているものに基づいて画像のみを変更します。

画像の代わりにViewControllersをロードするにはどうすればよいですか

4つのViewControllerがあります。

  • ViewController1
  • ViewController2
  • ViewController3
  • ViewController4

スライド1でViewController1を表示し、スライド2で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が読み込まれ、右にスワイプすると逆になります。

14
DannieCoderBoi

UIPageViewControllerと同じストーリーボードにビューコントローラー1〜4が定義されていて、それらのストーリーボード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)
    }
_

次に、メソッドの前後の2つのデリゲートで:

_    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に入力して、そのクラスをストーリーボードでPageItemControllerとして設定することができます(インデックスプロパティを持つため)。

または、各ビューコントローラを独自のクラスとして設定し、ランタイムプロパティの取得と設定を使用できます。

_controller.itemIndex_の代わりにbeforeメソッドとafterメソッドでcontroller.valueForKey("itemIndex") as Intを使用します

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

すべてのページにViewControllersをロードします。表示するすべての画像は、独自のViewController内にあります。それは次のように行われます:

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

あなたのすべてのページが同じレイアウトを使用している場合、インターフェイスビルダーでこのViewControllerを設計する以外に、ここで行うことは何もありません。ただし、すべてのページで異なるレイアウトを使用し、異なるデータを表示する場合は、最初にそれらのViewControllerをInterface Builderでプロトタイプ化/設計します。

次に、すべての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)
    }
}

最後に、指定したインデックスの正しいViewControllerを返すようにgetItemController関数を変更するだけです。ここでは、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
ergoon

これは素晴らしいレポです:

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

上記のEric Ferreiraのコードを機能させました(Xcode 6.4)。ページビューコントローラーを使用して、レルムデータベースのさまざまなデータを表示するラベルが付いた2つの完全に一意のビューコントローラーを表示したいと思いました。

私は2つのストーリーボードを使用するテストプロジェクトで作業しました。それぞれに、IBOutletを含む独自のクラスによって設定された1つのラベルが含まれ、ラベルにテキストを設定します。これにより、私の表示方法が適切にシミュレーションされます。レルムデータベースデータ。各ストーリーボードクラスはPageItemControllerを継承し、「itemIndex」変数を使用できるようにします。次に、PageItemControllerはUIViewControllerを継承し、継承チェーンを完成させます。

これが、完全にユニークなストーリーボードを使用しようとしている人に役立つことを願っています。

0