LoginSignup
56
61

More than 5 years have passed since last update.

背景透過なViewControllerをクロスディゾルブでモーダル表示

Posted at

iOS 7とiOS 8でやり方が違うので実は結構面倒だったりする。

  • iOS 7は遷移元のViewControllerに対してごにょごにょ
  • iOS 8は遷移先のViewControllerに対してごにょごにょ

iOS 7の場合

モーダルを出す時

modalPresentationStyle = .CurrentContext
modalTransitionStyle = .CrossDissolve
navigationController?.modalPresentationStyle = .CurrentContext
navigationController?.modalTransitionStyle = .CrossDissolve

presentViewController(controller, animated: animated, completion: {
  [weak self] () -> Void in

  // 遷移が終わったら元の状態に戻す。モーダルから戻ってきた後に別のモーダルを出そうとしてクロスディゾルブのままだったりする
  self?.modalPresentationStyle = .FullScreen
  self?.modalTransitionStyle = .CoverVertical
  self?.navigationController?.modalPresentationStyle = .FullScreen
  self?.navigationController?.modalTransitionStyle = .CoverVertical
})

モーダルを閉じる時

modalPresentationStyle = .CurrentContext
modalTransitionStyle = .CrossDissolve
navigationController?.modalPresentationStyle = .CurrentContext
navigationController?.modalTransitionStyle = .CrossDissolve

dismissViewControllerAnimated(true, completion: nil)

iOS 8の場合

モーダルを出す時

controller.modalPresentationStyle = .OverCurrentContext
controller.modalTransitionStyle = .CrossDissolve
presentViewController(controller, animated: animated, completion: nil)

モーダルを閉じる時

presentingViewController?.modalPresentationStyle = .OverCurrentContext
presentingViewController?.modalTransitionStyle = .CrossDissolve

// completionの中で、self?.presentingViewController とやってもnilなので
let p = presentingViewController

dismissViewControllerAnimated(true, completion: {
  [weak self] () -> Void in

  p?.modalPresentationStyle = .FullScreen
  p?.modalTransitionStyle = .CoverVertical
})

まとめると

モーダルを出す時

if iOS8以上 {
  controller.modalPresentationStyle = .OverCurrentContext
  controller.modalTransitionStyle = .CrossDissolve
} else {
  modalPresentationStyle = .CurrentContext
  modalTransitionStyle = .CrossDissolve
  navigationController?.modalPresentationStyle = .CurrentContext
  navigationController?.modalTransitionStyle = .CrossDissolve
}

presentViewController(controller, animated: animated, completion: {
  [weak self] () -> Void in

  if iOS8以上 { return }

  self?.modalPresentationStyle = .FullScreen
  self?.modalTransitionStyle = .CoverVertical
  self?.navigationController?.modalPresentationStyle = .FullScreen
  self?.navigationController?.modalTransitionStyle = .CoverVertical
})

モーダルを閉じる時

if iOS8以上 {
  presentingViewController?.modalPresentationStyle = .OverCurrentContext
  presentingViewController?.modalTransitionStyle = .CrossDissolve
} else {
  modalPresentationStyle = .CurrentContext
  modalTransitionStyle = .CrossDissolve
  navigationController?.modalPresentationStyle = .CurrentContext
  navigationController?.modalTransitionStyle = .CrossDissolve
}

let p = presentingViewController

dismissViewControllerAnimated(true, completion: {
  [weak self] () -> Void in

  if iOS8以上 {
    p?.modalPresentationStyle = .FullScreen
    p?.modalTransitionStyle = .CoverVertical
  }
})

やってられるか!!

というわけで、以下のようなextensionを用意する。

UIViewController+Extensions.swift
extension UIViewController {
  enum Transition {
    case Default, CrossDissolve
  }

  func tak_presentViewController(controller: UIViewController, animated: Bool, transition: Transition) {
    tak_presentViewController(controller, animated: animated, transition: transition, completion: nil)
  }

  func tak_presentViewController(controller: UIViewController, animated: Bool, transition: Transition, completion: (Void -> Void)?) {
    if iOS8以上 {
      controller.tak_setupTransition(transition)
    } else {
      tak_setupTransitionForIos7(transition)
    }

    presentViewController(controller, animated: animated, completion: {
      [weak self] () -> Void in

      if iOS8以上 { return }

      self?.tak_setupTransitionForIos7(.Default)
      completion?()
    })
  }

  func tak_dismissViewControllerAnimated(animated: Bool, transition: Transition) {
    tak_dismissViewControllerAnimated(animated, transition: transition, completion: nil)
  }

  func tak_dismissViewControllerAnimated(animated: Bool, transition: Transition, completion: (Void -> Void)?) {
    if iOS8以上 {
      presentingViewController?.tak_setupTransition(transition)
    } else {
      tak_setupTransitionForIos7(transition)
    }

    // completionの中で、self?.presentingViewController とやってもnilなので
    let p = presentingViewController

    dismissViewControllerAnimated(true, completion: {
      [weak self] () -> Void in

      if iOS8以上 {
        p?.tak_setupTransition(.Default)
      }

      completion?()
    })
  }

  // iOS7用
  private func tak_setupTransitionForIos7(transition: Transition) {
    switch transition {
    case .Default:
      modalPresentationStyle = .FullScreen
      modalTransitionStyle = .CoverVertical
    case .CrossDissolve:
      modalPresentationStyle = .CurrentContext
      modalTransitionStyle = .CrossDissolve
    }
    navigationController?.tak_setupTransitionForIos7(transition)
  }

  private func tak_setupTransition(transition: Transition) {
    switch transition {
    case .Default:
      modalPresentationStyle = .FullScreen
      modalTransitionStyle = .CoverVertical
    case .CrossDissolve:
      modalPresentationStyle = .OverCurrentContext
      modalTransitionStyle = .CrossDissolve
    }
  }
}

モーダルを出す時

tak_presentViewController(c, animated: true, transition: .CrossDissolve)

モーダルを閉じる時

tak_dismissViewControllerAnimated(animated: true, transition: .CrossDissolve)
56
61
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
56
61