Edited at

Popoverの2つの実装方法を比較する

More than 3 years have passed since last update.


はじめに

Popoverの実装方法に関して、従来使っていたUIPopoverControllerクラスがiOS9で廃止予定とされました。

(今さらですが、コード書き換えの際の備忘のために、)新旧でどう違うのかをメモしたいと思います。


違い

古い方法
新しい方法

発想
中身のViewControllerを入れたUIPopoverControllerに表示させる
中身のVCのpopoverPresentationControllerに条件をセットして、表示元のVCに表示させる

iOS
3.2〜9.0 (9.0でDeprecatedになりました。)
8.0〜

iPhone
不可

(adaptivePresentationStyleの指定でポップオーバーとモーダルの表示を切り替えられる。)

インスタンス管理
UIPopoverControllerのインスタンスを強参照で保持。不要になった時点でnilをセットして解放。
特に意識しないで済む。(VCのサイクルに従う。)

特に、iPhoneでPopoverを扱える点は大きな差です。

また、インスタンス管理がシンプルになるのも魅力的です。


古い方法のコード例

基本的にこのような構造になります。

ContentViewControllerが中身のviewControllerです。


ViewController.swift

class ViewController: UIViewController, UIPopoverControllerDelegate {

var popover: UIPopoverController?

@IBAction func tapUIPopoverController(_ sender: UIButton) {

//Only for iPad
if UIDevice.current.userInterfaceIdiom != .pad {
print("UIPopoverController is only for iPad.")
return
}

//Prepare the instance of ContentViewController which is the content of popover.
let contentVC = ContentViewController()
//set size
contentVC.preferredContentSize = CGSize(width: 300, height: 300)
//make popover controller
popover = UIPopoverController(contentViewController: contentVC)
//set delegate
popover?.delegate = self
//present
popover?.present(from: sender.frame, in: view, permittedArrowDirections: .any, animated: true)
}

//UIPopoverControllerDelegate for UIPopoverController
func popoverControllerDidDismissPopover(_ popoverController: UIPopoverController) {
//release
popover = nil
}

}



新しい方法の例


ViewController.swift

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {

@IBAction func tapModalPresentationStyle(_ sender: UIButton) {
//Prepare the instance of ContentViewController which is the content of popover.
let contentVC = ContentViewController()
//define use of popover
contentVC.modalPresentationStyle = .popover
//set size
contentVC.preferredContentSize = CGSize(width: 300, height: 300)
//set origin
contentVC.popoverPresentationController?.sourceView = view
contentVC.popoverPresentationController?.sourceRect = sender.frame
//set arrow direction
contentVC.popoverPresentationController?.permittedArrowDirections = .any
//set delegate
contentVC.popoverPresentationController?.delegate = self
//present
present(contentVC, animated: true, completion: nil)
}

/// Popover appears on iPhone
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}

}



新旧の比較デモ

上のコードが動くデモプロジェクトを作りました。

HowToDisplayPopover

https://github.com/hsylife/HowToDisplayPopover


感想

・そもそも、Popoverはあまり使われていない印象がありますが、個人的にはとても興味深いUIだと考えています。

・UXの面を考えた場合、画面遷移せずに何かを見ながら入力操作できる点や、指の移動が小さくて済む点で、モーダルやアクションシートよりも有利となることがある。

・開発の面からは、iPhone/iPadに共通のUIを持たせることができるので、デザイン、実装の手続きを一本化できる点が魅力。


関連リンク

UIPopoverPresentationController

UIPopoverController