Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

背景

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

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

スクリーンショット 2017-09-21 20.20.43.png

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

edgesForExtendedLayout = []

スクリーンショット 2017-09-21 20.50.06.png

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

スクリーンショット 2017-09-21 20.21.23.png

発生した問題

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

0921_test_trim.gif

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

0921_test_2.gif

原因と解決策

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

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

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

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

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

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

0921_test_3_trim.gif

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

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

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

スクリーンショット 2017-10-11 22.19.13.png

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

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

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

スクリーンショット 2017-10-11 22.22.24.png

スクリーンショット 2017-10-11 22.29.02.png

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした