1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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のメソッド
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?