94
69

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.

Auto Layoutのワーニング解読には「WTF?」が便利

Posted at

iOSエンジニアなら、Auto Layoutの制約がうまく設定できず、コンソールにワーニングがぞろぞろと出てくる事態に遭遇したことがあるのではないでしょうか。ずらずら並んだワーニングを読みたくない--そんな気持ちを少しでも軽減できるツール、WTF?(Why The Failure, Auto Layout?)を紹介しようと思います。

どんなツール?

Auto Layoutでワーニングログが出てきたときに、制約のコンフリクトを視覚化してくれるツールです。コードはGitHubで公開されています。

ここからは具体例を用いて説明します。

使用例

作りたいレイアウト

こんなレイアウトを作りたいと思って、コードでAuto Layouを使いつつ書いたとします。self.viewの上にグレーのview、そのまた上にUILabelを置いたレイアウトです。UILabelは左右中央、横幅はself.viewの0.85になるように制約をかけています。
スクリーンショット 2018-08-26 17.54.37.png

ワーニングログ

が、なぜかうまく描画されず、ワーニングログが出ています。

[LayoutConstraints] Unable to simultaneously satisfy constraints.
	Probably at least one of the constraints in the following list is one you don't want. 
	Try this: 
		(1) look at each constraint and try to figure out which you don't expect; 
		(2) find the code that added the unwanted constraint or constraints and fix it. 
	(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x60800009c2a0 h=--& v=--& UILabel:0x7fc150013250'\U30b7\U30e3\U30a4\U30cb\U30f3\U30b0\n\U30de\U30f3\U30c7\U3047\U3047\U3047\U3047'.width == 0   (active)>",
    "<NSLayoutConstraint:0x60c000280230 UILabel:0x7fc150013250'\U30b7\U30e3\U30a4\U30cb\U30f3\U30b0\n\U30de\U30f3\U30c7\U3047\U3047\U3047\U3047'.width == 0.85*UIView:0x7fc14de15fd0.width   (active)>",
    "<NSLayoutConstraint:0x60c000280d70 'UIView-Encapsulated-Layout-Width' UIView:0x7fc14de15fd0.width == 320   (active)>"
)
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x604000282ad0 'UIView-Encapsulated-Layout-Width' superView.width == 320   (active, names: superView:0x7f9ed14073d0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

WTF?に入力してみる

ここで今回のツールを使ってみたいと思います。トップページはこのようになっています。
スクリーンショット 2018-08-26 18.04.40.png
ここの記述に従い、先程のワーニングログの中の、()で囲まれた部分をペーストし、「Go!」ボタンをクリックすると…
スクリーンショット 2018-08-26 18.09.12.png
このように視覚的に表示されます。でも、まだわかりにくいかもしれません。ということで今度はviewにidentifierを付けてもっと見やすくしてみましょう。次の3行を足します。

self.view.accessibilityIdentifier = "superView"
coverView.accessibilityIdentifier = "coverView"
messageLabel.accessibilityIdentifier = "messageLabel"

もしStoryboard上でレイアウトを描いている場合はXcodeの右ペインからAccessibilityのIdentifierから設定をしてください。
スクリーンショット 2018-08-26 18.14.43.png
この状態でもう一度WTF?にワーニングを入力すると…
スクリーンショット 2018-08-26 18.16.50.png
非常に見やすくなりました。

解読してみる

一番目の制約からしてダメそうです。messageLabelのwidthが0になっています。
スクリーンショット 2018-08-26 18.16.50.png
一番後ろに注釈の*印が付いているので、注釈を見てみます。
スクリーンショット 2018-08-26 18.16.50 2.png
「もしこの制約が意図通りではなかったらtranslatesAutoresizingMaskIntoConstraintsをfalseにしてみてね」と言っています。自分でコード上で生成したviewをAuto Layoutに適用させるときには、こいつをfalseにする必要があるのに忘れていたようです。

ということで次のコードを足して、ワーニングを解消することができました。

coverView.translatesAutoresizingMaskIntoConstraints = false
messageLabel.translatesAutoresizingMaskIntoConstraints = false

補足

全てのワーニングが解析できるかというとそうでもないようです。
スクリーンショット 2018-08-26 18.51.54.png

まとめ

  • どんな制約が絡み合っているのかを確認したい場合はWhy The Failure, Auto Layout?を使うと便利
  • identifierを付けるともっとわかりやすくなる
94
69
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
94
69

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?