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

Debugging your layout ([WWDC2015] Mysteries of Auto Layout, Part 2より)

More than 1 year has passed since last update.

WWDC2015のセッションであるMysteries of Auto Layout, Part 2から、Auto Layoutのデバッグの部分だけ抜粋してざっくりまとめました。

レイアウトのデバッグ

ログを読む

Auto Layoutを使ってUIを作っていると、たまに意図しないレイアウトになることがあります。この時に出るログについて少し見ていきます。

スクリーンショット 2018-08-11 22.32.13.png

まず一番下をチェックします。これはエンジンによって壊された制約です。必ずしもこの制約が原因とは限りませんが取り掛かりとしては良いと言えます。

スクリーンショット 2018-08-11 22.26.16.png

まず最初にtranslatesAutoResizingMaskをチェックします。今回の場合、Saturnのaspect比の制約が壊れているので、この周辺の制約を見ていきます。

Saturn自体はsuperviewに対するleadingの制約、trailingの制約、topの制約、labelに対するbottomの制約は問題ありません。なので今度は接しているlabelを詳しく見ていきます。

このlabelには先程のSaturnのbottomとlabelのtopをつなぐ制約と、labelのtopとsuperviewのtopをつなぐ制約がついています。Saturnは100ポイント以上あると思われるので、この制約がまずそうです。

スクリーンショット 2018-08-11 22.57.22.png

identifierを付けてログを読みやすくする

ログを読むことは難しくありませんが、より読みやすくしてみましょう。

スクリーンショット 2018-08-11 23.09.30.png スクリーンショット 2018-08-11 23.11.32.png

右側の方が見やすいと思います。このようにするためにはidentifierを付ける必要があります。明示的に制約を付けている場合は次のように指定します。

labelToTop.identifier = @"labelToTop.identifier";

もしビジュアルフォーマットを使っている場合は、ループ処理を利用して配列内の全ての制約に対して同じidentifierを付けます。

for (NSLayoutConstraint *constraint in verticalLayout)
{
    constraint.identifier = @"verticalLayout";
}

Interface Builderで設定する場合は以下の箇所から設定します。

スクリーンショット 2018-08-11 23.44.19.png

ログを理解する

identifierはviewに対しても付けることができます。これにより、ログを解読する労力を減らすことができます。

もしログが大量すぎる場合は1方向だけの制約を出力してくれるconstraintsAffectingLayoutForAxis (iOS用)、constraintsAffectingLayoutForOrientation (OS X用)を使うと良いです。

ブレークポイントを張ってデバッガにconstraintsAffectingLayoutForAxisを入力してSaturnの縦の制約を出力してみます。ここではメモリアドレスではなくidentifierで指定できるようにしています。verticalは1、horizontalは0です(現在Swiftで書く場合はself.view.constraintsAffectingLayout(for: .vertical)のような形になります)。

スクリーンショット 2018-08-12 13.42.20.png

topの制約は問題なさそうなこと、Saturnの下にも制約があること、labelのtopからsuperviewに伸びている制約があることがわかります。ここから怪しい制約を発見することもできます。

ログを理解するためにすると良いことは以下の通りです。

  • 下から見ていく
  • 最初にtranslatesAutoresizingMaskIntoConstraintsの設定をチェックする
  • identifierを設定する
  • constraintsAffectingLayoutForAxis:を使う

制約の曖昧さを解消する

今度は制約が曖昧で、解決方法が複数存在する場合について見ていきます。

レイアウトが正しく表示されない原因

考えられる理由は例えば次の通りです。

  • 制約が足りない
  • 優先度がコンフリクトしている

contentHuggingPriority(大きくなりにくさ / コンテンツに沿う優先度)とcompressionResistancePriority(コンテンツの潰れにくさ)の設定によってはコンフリクトしてレイアウトが崩れてしまうことがあります。

解決するために役立つツール

以下のツールから手がかりが得られます。

  • Interface Builderの赤/黄色のアイコン
  • _autolayoutTrace
    • IBを使用していないときに便利
    • 曖昧なレイアウトをビューの階層情報とともに出力してくれる
  • ビューデバッガー
  • exerciseAmbiguityInLayout
    • 曖昧だとわかっているviewに対して使う
    • 制約を満たす範囲でランダムに制約を付けてくれる
  • hasAmbiguousLayout
    • 曖昧なレイアウトかどうかをBoolで返す

デバッグのポイント

  • レイアウトするのに必要な情報は何かを考える
  • うまくいかないときはログを使う
    • ビューや制約にidentifierを付けておく
  • 定期的にチェックする
    • 単体テストとして入れてしまうなど
  • ツールを使う
    • Interface Builderのアイコン
    • ビューデバッガー
    • LLDBのメソッド
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
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