iOSエンジニアなら、Auto Layoutの制約がうまく設定できず、コンソールにワーニングがぞろぞろと出てくる事態に遭遇したことがあるのではないでしょうか。ずらずら並んだワーニングを読みたくない--そんな気持ちを少しでも軽減できるツール、WTF?(Why The Failure, Auto Layout?)を紹介しようと思います。
どんなツール?
Auto Layoutでワーニングログが出てきたときに、制約のコンフリクトを視覚化してくれるツールです。コードはGitHubで公開されています。
ここからは具体例を用いて説明します。
使用例
作りたいレイアウト
こんなレイアウトを作りたいと思って、コードでAuto Layouを使いつつ書いたとします。self.viewの上にグレーのview、そのまた上にUILabelを置いたレイアウトです。UILabelは左右中央、横幅はself.viewの0.85になるように制約をかけています。
ワーニングログ
が、なぜかうまく描画されず、ワーニングログが出ています。
[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?に入力してみる
ここで今回のツールを使ってみたいと思います。トップページはこのようになっています。
ここの記述に従い、先程のワーニングログの中の、()
で囲まれた部分をペーストし、「Go!」ボタンをクリックすると…
このように視覚的に表示されます。でも、まだわかりにくいかもしれません。ということで今度はviewにidentifierを付けてもっと見やすくしてみましょう。次の3行を足します。
self.view.accessibilityIdentifier = "superView"
coverView.accessibilityIdentifier = "coverView"
messageLabel.accessibilityIdentifier = "messageLabel"
もしStoryboard上でレイアウトを描いている場合はXcodeの右ペインからAccessibilityのIdentifierから設定をしてください。
この状態でもう一度WTF?にワーニングを入力すると…
非常に見やすくなりました。
解読してみる
一番目の制約からしてダメそうです。messageLabelのwidthが0になっています。
一番後ろに注釈の*印が付いているので、注釈を見てみます。
「もしこの制約が意図通りではなかったらtranslatesAutoresizingMaskIntoConstraints
をfalseにしてみてね」と言っています。自分でコード上で生成したviewをAuto Layoutに適用させるときには、こいつをfalseにする必要があるのに忘れていたようです。
ということで次のコードを足して、ワーニングを解消することができました。
coverView.translatesAutoresizingMaskIntoConstraints = false
messageLabel.translatesAutoresizingMaskIntoConstraints = false
補足
全てのワーニングが解析できるかというとそうでもないようです。
まとめ
- どんな制約が絡み合っているのかを確認したい場合はWhy The Failure, Auto Layout?を使うと便利
- identifierを付けるともっとわかりやすくなる