iOS 13以上のiPhoneで自前のポップオーバー画面とAirPrint画面を表示すると挙動に差異がある理由

iOS 13以上のiPhoneから、ポップオーバー画面のデフォルトのスタイルが、全画面表示から疑似全画面表示（公式な名称が見つけられなかったので、仮でこのように読んでおく）に変更されている

それらの具体的な違いは以下の通りである

| 挙動 | 全画面表示(～iOS 12) | 疑似全画面表示(iOS 13～) |
|:--|:--|:--|
| 表示サイズ | 全画面表示 | 上部に隙間が空いた状態でほぼ全画面表示 |
| 閉じ方 | アプリ側で制御のみ | アプリ側で制御、あるいは、**ユーザーが画面全体を下にスワイプ** |

この際、自前で用意したポップオーバーと、OSが用意してくれているプリント画面では微妙に表示に差異があったため、その理由と差異をなくす方法をメモしておく

# 差異の詳細

以下のような、自作ポップオーバー画面を表示するボタンと、プリント画面を表示するボタンを持つサンプルアプリで挙動を確認する

```ViewController.swift
import UIKit
import WebKit

class ViewController: UIViewController {
    @IBOutlet weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = .blue

        let showGreenScreenButton = UIButton()
        showGreenScreenButton.setTitle("GreenScreen", for: .normal)
        showGreenScreenButton.addTarget(self, action: #selector(showGreenScreen(_:)), for: .touchUpInside)

        view.addSubview(showGreenScreenButton)

        let showAirPrintButton = UIButton()
        showAirPrintButton.setTitle("AirPrint", for: .normal)
        showAirPrintButton.addTarget(self, action: #selector(showAirPrintScreen(_:)), for: .touchUpInside)

        view.addSubview(showAirPrintButton)

        // ...
    }

    @objc private func showGreenScreen(_ sender: Any) {
        let viewController = UIViewController()
        viewController.view.backgroundColor = .green

        self.present(viewController, animated: true, completion: nil)
    }

    @objc private func showAirPrintScreen(_ sender: Any) {
        let printController = UIPrintInteractionController.shared

        let formatter = webView.viewPrintFormatter()
        printController.printFormatter = formatter

        printController.present(animated: true, completionHandler: nil)
    }
}
```

<img width="375" alt="01_親View.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/c1ae81c3-1bc5-5bce-d477-f4af6064bd07.png">

「GreenScreen」ボタンをタップすると、青のViewが奥まった場所に引っ込むアニメーションとともに、緑のViewが前面に出てくる
![02_自作ポップオーバー画面.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/cf7441b7-0750-be5a-9b93-45bc31214d9a.gif)

一方で、「AirPrint」ボタンをタップすると、AirPrint画面が表示されるものの、先ほどのような青のViewが奥まった場所に引っ込むアニメーションは発生しない
![03_AirPrint.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/072f80d7-125b-0ce2-4204-ac0b4d799fbd.gif)

# 差異の理由
これは、自作のポップオーバー画面は親となるUIViewControllerが存在している一方で、AirPrint画面はiOSのシステムであり単純に表示すると**親となるUIViewControllerが存在していないため**である

# 差異をなくす方法
デリゲート設定で親となるUIViewControllerを指定すると、自前のポップオーバー画面と同様の挙動になる

```swift:ViewController.swift
class ViewController: UIViewController {

// ...

    @objc private func showAirPrintScreen(_ sender: Any) {
        let printController = UIPrintInteractionController.shared

        let formatter = webView.viewPrintFormatter()
        printController.printFormatter = formatter

        printController.delegate = self // デリゲート設定を追加

        printController.present(animated: true, completionHandler: nil)
    }

// ...

}

extension ViewController: UIPrintInteractionControllerDelegate {
    func printInteractionControllerParentViewController(
        _ printInteractionController: UIPrintInteractionController) -> UIViewController? {
        return self
    }
}
```

![04_AirPrint_親ViewController指定あり.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/a190c2f7-552b-d0ca-4a07-b5e0df1d5b86.gif)

# 参考
- https://developer.apple.com/documentation/uikit/uiprintinteractioncontrollerdelegate