iOS11 + Xcode9.0でedgesForExtendedLayoutの値を空にしていると、UITableViewのドリルダウンでアニメーションが崩れる

# 背景
iOS7からUIViewControllerへ追加されたプロパティに、**edgesForExtendedLayout**があります。

- [edgesForExtendedLayout - UIViewController | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621515-edgesforextendedlayout)

このプロパティはNavigation Barの下にViewへ回り込ませるためのもので、デフォルトでは回り込むように値が設定されています。

<img width="559" alt="スクリーンショット 2017-09-21 20.20.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/29477/db94b523-7bd5-fdd6-3377-a39615bc4813.png">


ここへ空を代入するか、Storyboardで「Under Top Bars」のチェック外すと、回り込みがなくなり、ViewはNavigation Barの下からスタートします。

```swift
edgesForExtendedLayout = []
```

<img width="413" alt="スクリーンショット 2017-09-21 20.50.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/29477/5cd03bc2-9059-1018-11ae-8e07f5882d91.png">

ちょっとわかりにくいですが、Navigation Barの下にはTableViewが回り込んでいません。

<img width="559" alt="スクリーンショット 2017-09-21 20.21.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/29477/74a9e3ca-9c32-7cf4-10b2-00d5f9a31120.png">

# 発生した問題

この状態のアプリをXcode9.0でビルドすると問題が発生します。iOS11端末へ入れたときにTableViewだと画面遷移のアニメーションが不自然になります。

![0921_test_trim.gif](https://qiita-image-store.s3.amazonaws.com/0/29477/7584895e-ae95-646c-6ae8-9e7080df1011.gif)

微妙ですが、ナビゲーションを上る時に20ptほどの隙間が存在していて、上にスクロールしながら遷移します。edgesForExtendedLayoutをいじっていない時は以下のような挙動になります。こちらはきれいに遷移しています。

![0921_test_2.gif](https://qiita-image-store.s3.amazonaws.com/0/29477/91d0e410-2a16-f024-5bf3-ed14f369d194.gif)


# 原因と解決策

調べてみると、こちらにバグレポートとして似たような現象が報告されていました。

- [iOS 11: Pushing/Popping scrollView on navController with opaque navBar visibly adjusts content during transition](http://openradar.appspot.com/34465226)

iOS11からUIScrollViewへ導入された**adjustedContentInset**が悪さをしているようです。

- [adjustedContentInset - UIScrollView | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscrollview/2902259-adjustedcontentinset)

このプロパティは、UINavigationControllerへ配置されたUIScrollViewに対して自動でInset値を付けてくれるものです。
UIScrollViewへ自前でcontentInsetsを設定していると、このプロパティの影響でレイアウト崩れを起こすという報告がいくつかされています。

- [iOS11 で UIScrollView の contentInsetがずれる問題](https://qiita.com/peka2/items/b6301a0c06cc13286296)
- [iOS11からUITableViewにスペースができてしまう](https://qiita.com/tatetate55/items/1c948a27de3cc4851202)

対策としては、contentInsetAdjustmentBehaviorの値にneverを設定すればいいようです。

- [contentInsetAdjustmentBehavior - UIScrollView | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior)

```swift
if #available(iOS 11.0, *) {
    tableView.contentInsetAdjustmentBehavior = .never
}
```

この設定をしてみた所、今回のケースでも正常な状態となり、自然なアニメーションへ戻りました。

![0921_test_3_trim.gif](https://qiita-image-store.s3.amazonaws.com/0/29477/785539f5-427c-ca37-b5c6-5862e2b675cb.gif)

他のケースと異なり、UITableViewで特にcontentInsetsを設定していなくてもadjustedContentInsetの影響を受けることがあったので、こちらへまとめておきます。
バグレポートとして報告されていることから、将来のバージョンでは修正されているかもしれません。

# 追記 (2017/10/11)　: contentInsetAdjustmentBehaviorをneverにした時のiPhoneXでのSafeArea問題

上記設定をした時に気をつける必要がある問題として、UIScrollViewが勝手にやってくれるSafe Area設定が無効になってしまうという点があります。例えば、下部にUITabBarなどを置かずにUITableViewが一番下に接触している場合、iPhoneXで以下の状態になります。 Home Indicatorと一番下のセルが被ってしまい、ガイドライン的によろしくない状態となってしまいます。

<img width="554" alt="スクリーンショット 2017-10-11 22.19.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/29477/8baf6469-a6be-84f9-e7d0-fec24ee38aad.png">

その問題を解消するために、frameやinsetsの値を変更する時のタイミングなどで、safeAreaInsetsのbottomを入れてやる必要があるでしょう。(safeAreaInsetsの全てをそのまま設定するとLandscapeにした時にTableViewでは左右のレイアウトが崩れてしまいます。)

```swift
override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if #available(iOS 11.0, *) {
        tableView.contentInset.bottom = view.safeAreaInsets.bottom
    }
}
```

そうすると以下のようにHome Indicatorの領域の上までスクロールされるようになります。

<img width="554" alt="スクリーンショット 2017-10-11 22.22.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/29477/b19318b6-269c-348a-d48a-6a96a5d79243.png">

<img width="982" alt="スクリーンショット 2017-10-11 22.29.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/29477/aa6a6de2-929e-4f8c-a541-991bbd053be0.png">


# 参考資料
- [edgesForExtendedLayout - UIViewController | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621515-edgesforextendedlayout)
- [iOS 11: Pushing/Popping scrollView on navController with opaque navBar visibly adjusts content during transition](http://openradar.appspot.com/34465226)
- [adjustedContentInset - UIScrollView | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscrollview/2902259-adjustedcontentinset)
- [iOS11 で UIScrollView の contentInsetがずれる問題](https://qiita.com/peka2/items/b6301a0c06cc13286296)
- [iOS11からUITableViewにスペースができてしまう](https://qiita.com/tatetate55/items/1c948a27de3cc4851202)
- [contentInsetAdjustmentBehavior - UIScrollView | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior)