8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UIPageViewControllerを使ってみる

Posted at

UIPageViewControllerを使ってみた

目的

既存のアプリの画像プレビュー画面をつくるため

状況として

  • NavigationControllerとTabControllerのついたViewからpushされる
  • AutoLayoutを使用している

この2つの時。ちょっとつまづくところや自分で工夫してみたところがあるので

導入方法

  1. StoryboardにPageViewControllerを設置してsegueを貼る
  2. Storyboardに表示したいページになるViewControllerを設置する
  3. 今回はAutoLayoutがナビゲーションバーの高さとタブバーの高さに依存してほしいから子となるViewControllerにPageViewControllerから適当に使わないsegueを貼った(もっといい方法あれば教えて下さい。。。)
  4. 子のViewControllerは画像を表示するだけなのでOutletだけ接続しWillAppearの段階で画像を反映させるようにするだけでオーケー
  5. PageViewControllerにはDataSourceとDelegateを継承して設定(デフォルトのサンプルだとDataSourceとDelegateの継承クラスは2つにわけてるけど今回はいっぺんに)

コードはこんな感じです。Utility以下は必ず作らないといけないわけではなくて何らかの形でその処理の内容が実現できてればいいです。

import UIKit

class ImagePreViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    var pageData: NSMutableArray!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
        
        let startViewController: PreViewController = self.viewControllerAtIndex(0, storyboard: self.storyboard!)!
        let viewControllers = [startViewController]
        self.setViewControllers(viewControllers, direction: .Forward, animated: false, completion: {done in })
        
        self.dataSource = self
        self.view.gestureRecognizers = self.gestureRecognizers
    }
    
    // pageViewController関連----------------------------------------------------
    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        var index = self.indexOfViewController(viewController as! PreViewController)
        if index == 0 || index == NSNotFound {
            return nil
        }
        index--
        return self.viewControllerAtIndex(index, storyboard: viewController.storyboard!)
    }
    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        var index = self.indexOfViewController(viewController as! PreViewController)
        if index == self.pageData.count - 1 || index == NSNotFound {
            return nil
        }
        index++
        return self.viewControllerAtIndex(index, storyboard: viewController.storyboard!)
    }
    // 向きはPortrait限定なので常に表示されるページは一個
    func pageViewController(pageViewController: UIPageViewController, spineLocationForInterfaceOrientation orientation: UIInterfaceOrientation) -> UIPageViewControllerSpineLocation {
        let currentViewController = self.viewControllers![0]
        let viewControllers = [currentViewController]
        self.setViewControllers(viewControllers, direction: .Forward, animated: true, completion: {done in })
        self.doubleSided = false
        return .Min
    }
    
    // Utility------------------------------------------------------------------
    func indexOfViewController(viewController: PreViewController) -> Int {
        if let dataObject: AnyObject = viewController.imageData {
            return self.pageData.indexOfObject(dataObject)
        } else {
            return NSNotFound
        }
    }
    func viewControllerAtIndex(index: Int, storyboard: UIStoryboard) -> PreViewController? {
        if self.pageData.count == 0 || index >= self.pageData.count {
            return nil
        }
        let preViewController = storyboard.instantiateViewControllerWithIdentifier("PreViewController") as! PreViewController
        preViewController.imageData = self.pageData[index] as! NSData
        return preViewController
    }
}

pageViewControllerのviewControllerBeforeうんにゃらとviewControllerAfterうんにゃらが前後のViewを決めるdelegateメソッドになっています。内容はわりとここを参考にしましたがようは今表示されてるViewが用意されてるViewの何枚目かを判断して決めているだけです。実際にはpageDataに画像のNSDataをぶっこむ処理をsegueのところでやっています。

NavigationController+TabBarController+PageViewController

AutoLayoutのための工夫は先程言いました。しかしなにもしないままだと実はタップするまでNavigationBarの下にViewが表示されてしまいその後潜るという挙動が発生します。
このことに関してはここの追記を参考にAdjust Scroll View Insetsのチェックを外すことで直せました。

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?