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

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

https://www.wtfautolayout.com/

# どんなツール？

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

https://github.com/johnpatrickmorgan/wtfautolayout

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

# 使用例

## 作りたいレイアウト

こんなレイアウトを作りたいと思って、コードでAuto Layouを使いつつ書いたとします。self.viewの上にグレーのview、そのまた上にUILabelを置いたレイアウトです。UILabelは左右中央、横幅はself.viewの0.85になるように制約をかけています。
<img width="300" alt="スクリーンショット 2018-08-26 17.54.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/35564ad6-877b-00e4-9064-295660229ce5.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?に入力してみる

ここで今回のツールを使ってみたいと思います。トップページはこのようになっています。
<img width="800" alt="スクリーンショット 2018-08-26 18.04.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/708dc70f-1660-1238-8794-4f51e2371eb8.png">
ここの記述に従い、先程のワーニングログの中の、`（）`で囲まれた部分をペーストし、「Go!」ボタンをクリックすると…
<img width="900" alt="スクリーンショット 2018-08-26 18.09.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/d5ba0300-690a-15b5-b53b-7e7424304b64.png">
このように視覚的に表示されます。でも、まだわかりにくいかもしれません。ということで今度はviewにidentifierを付けてもっと見やすくしてみましょう。次の3行を足します。

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

もしStoryboard上でレイアウトを描いている場合はXcodeの右ペインからAccessibilityのIdentifierから設定をしてください。
<img width="250" alt="スクリーンショット 2018-08-26 18.14.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/23108270-b5dd-e742-afe3-b88068455ea5.png">
この状態でもう一度WTF?にワーニングを入力すると…
<img width="900" alt="スクリーンショット 2018-08-26 18.16.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/81d09b86-3e3a-5963-fd96-677b5608e08b.png">
非常に見やすくなりました。

## 解読してみる

一番目の制約からしてダメそうです。messageLabelのwidthが0になっています。
<img width="900" alt="スクリーンショット 2018-08-26 18.16.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/ea832d67-2cd9-9d89-9af9-06227f0edb5e.png">
一番後ろに注釈の*印が付いているので、注釈を見てみます。
<img width="900" alt="スクリーンショット 2018-08-26 18.16.50 2.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/fb0cf9c6-8461-8dbe-950e-70511208a8b8.png">
「もしこの制約が意図通りではなかったら`translatesAutoresizingMaskIntoConstraints`をfalseにしてみてね」と言っています。自分でコード上で生成したviewをAuto Layoutに適用させるときには、こいつをfalseにする必要があるのに忘れていたようです。

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

```swift
coverView.translatesAutoresizingMaskIntoConstraints = false
messageLabel.translatesAutoresizingMaskIntoConstraints = false
```

# 補足

全てのワーニングが解析できるかというとそうでもないようです。
<img width="900" alt="スクリーンショット 2018-08-26 18.51.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/100736/64e6a5f1-d692-2a3c-a181-1c2bf34837a7.png">

# まとめ

* どんな制約が絡み合っているのかを確認したい場合はWhy The Failure, Auto Layout?を使うと便利
* identifierを付けるともっとわかりやすくなる