【書評】初学者はもちろん、中級者にもオススメのAuto Layout解説書「よくわかるAuto Layout」の紹介

著者の川邉さん（[@jeffsuke](https://twitter.com/jeffsuke)）および出版社のリックテレコム様より<b>『よくわかるAuto Layout - iOSレスポンシブデザインをマスター』</b>をご献本いただきました。


<img src="https://qiita-image-store.s3.amazonaws.com/0/3180/f2406c9d-4189-ee35-859e-85fee46f4624.jpeg" width="400">


タイトルの通りAuto Layoutの解説書で、豊富な図やスクリーンショットを用いて、非常にわかりやすく書かれています。前書きによると、本書の対象読者は

> 過去一度はXcodeを用いてiOSアプリをつくったことがあるが、<span class="deco" style="color:#FF0000;font-weight:bold;">Auto Layoutとサイズクラスを用いたAdaptive Layoutと言われると尻込みしてしまう</span>開発者

とのこと。


なんかもうベストセラーになったりしてるらしく、

<blockquote class="twitter-tweet" data-cards="hidden" data-lang="ja"><p lang="ja" dir="ltr">「よくわかるAuto Layout iOSレスポンシブデザインをマスター」発売しました。<a href="https://twitter.com/tokorom">@tokorom</a> 監修。今、モバイルプログラミング分野でベストセラーらしいです！ <a href="https://t.co/wx7ZfuWVdf">https://t.co/wx7ZfuWVdf</a></p>&mdash; Yusuke Kawanabe (@jeffsuke) <a href="https://twitter.com/jeffsuke/status/743719588039294983">2016年6月17日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


<b>AutoLayoutの必要性</b>は今更僕が説くことでもないですし、<b>監修は名著『[UIKit詳解リファレンス](http://www.amazon.co.jp/exec/obidos/ASIN/4897978440/22301-22/ref=nosim/)』の著者 所さん</b>！


ということで、これはもう

- <b>iOSアプリ開発に携わっている</b>（携わろうとしている）
- <b>AutoLayoutがよくわかってない</b>

という方はもう買うしかないでしょう。買いましょう！



<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4865940324/22301-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/51ELGPlwjgL._SL160_.jpg" alt="よくわかるAuto Layout  iOSレスポンシブデザインをマスター" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4865940324/22301-22/ref=nosim/" name="amazletlink" target="_blank">よくわかるAuto Layout  iOSレスポンシブデザインをマスター</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 16.07.17</div></div><div class="amazlet-detail">川邉 雄介 <br />リックテレコム <br />売り上げランキング: 14,747<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4865940324/22301-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jpで詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>

（Kindle版もありますが、**固定レイアウト**のようです。）



・・・と、Auto Layoutに自信のない初学者の方には当然のようにオススメなのですが、<b>AutoLayoutがそれなりにわかっている</b>（と自分では思っていた）僕が読んでも、<b>勉強になったポイント</b>がいくつもありました。以下で紹介していきます。


##Content Hugging Priority と Content Compression Resistance Priority と Instrinsic Content Size

250とか750とかのデフォルト値が振られてるアレです。

<img width="258" alt="layout2.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/3180/7c80b6f3-3ad4-71db-6786-0c887859cc84.jpeg">


Auto Layoutはわかっているつもりでも、このへんの理解が曖昧なまま**warningが出たときになんとなく優先度をいじってみたり**している、みたいな人は実は多いのではないでしょうか。私がまさにそうでしたが、本書では詳細かつ明解に解説されていて、曖昧に理解していたところがスッキリしました。以下メモ。

- それぞれ Instrinsic Content Size についての**「大きくなりにくさ」「小さくなりにくさ」**を意味している [^1]
- NSLayoutConstraintの優先度の値が**同値の場合は、NSLayoutConstraintによる制約が優先**される


[^1]: この訳はAppleのドキュメントにあったのか著者のオリジナルかわかりませんが、簡潔で秀逸な訳だなと思いました


##レイアウトのライフサイクル（p35〜）

<b>1. 制約の更新、2. フレームの更新、3. レンダリング</b>というiOSにおけるレイアウトの3つのステップについて詳細に解説されています。


恥ずかしながら `updateConstraintsIfNeeded`, `layoutIfNeeded`, `layoutSubviews`, `setNeedsDsplay` といったメソッドでそれぞれ<b>何が行われるのか、または何が行われないのか</b>、といったことの理解が曖昧だったのですが、順序立ててわかりやすく解説されていて非常に勉強になりました。

###1. 制約の更新

- `updateConstraints` が呼ばれる
- <b>ボトムアップ</b>（子ビューから親ビュー）に制約の計算が実行される
- 制約の有効／無効化、優先度変更、追加／削除などをトリガに実施される
- この<b>制約の更新を明示的に実行</b>したい場合には `updateConstraintsIfNeeded` もしくは `setNeedsUpdateConstraints` を呼ぶ

###2. フレームの更新

- `layoutSubviews` が呼ばれる
- `layoutSubviews` が呼ばれると `updateConstraintsIfNeeded` も呼ばれ、必要に応じて制約の更新も行われる
- <b>トップダウン</b>（親ビューから子ビュー）に実施される
- ビューのフレームの変更・サブビューの追加・削除等をトリガに実施される
- 明示的に実行したい場合には `layoutIfNeeded` もしくは `setNeedsLayout` を呼ぶ
- `layoutSubview` をオーバーライドすると、`super.layoutSubviews()` の時点で既に制約の更新が完了しているので、そのレイアウト情報を用いて何らかの処理を実行したい場合に有効（+この方法で無限スクロールを実現する例）

###3. レンダリング

- `drawRect:` が呼ばれる
- 明示的に実行したい場合には `setNeedsDisplay` または `setNeedsDisplayInRect:` を呼ぶ


また `viewWillLayoutSubviews` と `viewDidLayoutSubviews` についても、それぞれの段階では（レイアウトサイクルの）どのステップは完了していて何は完了していないのか、というところの理解がスッキリしました。

###viewWillLayoutSubviews

- この時点では、サブリューのレイアウトは決定されていないが、画面の向きは決定している
- この後、「制約の更新」と「フレームの更新」が実施される

###viewDidLayoutSubviews

- <b>layoutSubviews による「フレームの更新」が完了</b>すると呼ばれる
- <b>この後にレンダリングが行われる</b>ので、viewDidAppearはこれより後に呼ばれる


##UIWindowの話

直接Auto Layoutとは関係ないですが、iOSでUIを実装するにあたって<b>UIWindowに関して知っておいた方がいいこと</b>が簡潔に解説されています。`windowLevel` による重なり順の話とか、画面サイズを取得する場合に

```swift
UIScreen.mainScreen().bounds
```

と

```swift
UIScreen.sharedAppliation().keyWindow?.bounds
```

はどう違うか、とか。


##UIStackView

iOS 9で追加された UIStackView についても、10ページを使ってしっかり解説されています。


ちなみに

> <b>Start with Stack View, use constraints as needed</b>

（**まずはStack Viewを使って、必要に応じてconstraintsを使おう**）


と[WWDCのセッションでも言われていた](https://speakerdeck.com/kishikawakatsumi/uistackview-storyboard-reference-corespotlight-api-ios-9-bootcamp)とか。


##コードで制約を設定する & NSLayoutAnchor

僕は基本的にはIB/Storyboardで制約を貼るのですが、仕事柄多くのプロジェクトに関わるので、「IB/Storyboard使わない派」な方々のコードに触れる機会も度々ありまして、コードで制約を設定することもたまにあります。


本書では、NSLayoutConstraint のイニシャライザを使う方法、VFL (Visual Format Language)を使う方法、<b>iOS 9 で追加されたNSLayoutAnchor</b>を使う方法等、まるまる一章を使ってその方法が解説されています。


ちなみに**そろそろiOS 9の機能を使ってもいい（iOS 8を切ってもいい）空気**になってきたと個人的には感じていますが、<b>NSLayoutAnchor を使うと超シンプルかつ直感的にレイアウト制約をコードから設定</b>できるようになります。


```swift:before
NSLayoutConstraint(item: subview,
                   attribute: .Leading,
                   relatedBy: .Equal,
                   toItem: view,
                   attribute: .LeadingMargin,
                   multiplier: 1.0,
                   constant: 0.0).active = true
```


```swift:after
let margins = view.layoutMarginsGuide
subview.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor).active = true
```


本章末尾のコラムではAuto Layoutを簡潔に書くためのオープンソースライブラリもいくつか紹介されています。


##その他、細かい話

###Auto Layout のアルゴリズム

> この線型方程式系を解くアルゴリズムは、**Greg J. Badros と Alan Borning、Peter J. Stuckey によって2001年に発表された、制約充足問題を説く Cassowary というツールキットで用いられたアルゴリズム**を使用しています。（p.15）


明日から開発に活かせる、という話ではないのですが、こんなこともサラッと書かれていて、しっかり調べて執筆されている書籍なんだなということが伺えます。


###外接矩形（alignment rects）をデバッグ時に確認する

[Edit Scheme] > [Run] > [Arguments] の [Arguments Passed On Launch] に `-UIViewShowAlignmentRects` を追加してチェックを入れると、**実行時に外接矩形が表示**される、というTips。


###NSLayoutAttributeのLeft/RightとLeading/Trailingの違い

基本的にLeading/Trailingを使ってたので意識したことなかったですが、アラビア語とかヘブライ語のように<b>右から左へ書く言語</b>ではLeading/TrailingがそれぞれRight/Leftと同値となるそうです。


###制約の矛盾が実行時に起きたときのエラーメッセージの見方

実行時にぶわーっと出てくるエラーメッセージ、ありますよね。僕は最近だとAutoLayoutを使ったアニメーションをやろうとして何かが間違っててこれが出てきました。で、**エラーメッセージ読んでもどの制約が悪いのかわかりづらい**、と思ってたんですが、制約にちゃんとidentifierふればいいみたいです。（p86）


###Xcode 7 の Storyboard Reference

Xcode 7 で追加された [Refactor to Storyboard...] メニューからの **Storyboard の分割**方法もしっかり書かれています。


###Auto LayoutのデバッグTips

UIView に `exerciseAmbiguityInLayout()` なるメソッドがあり、これを用いると曖昧な制約を持つビューオブジェクトのフレームを、**制約を満たす範囲でランダムに変更してくれる**そうです。


他にもオブジェクトが持つインスタンス変数名と値を吐いてくれる `_ivarDescription` メソッド((※Privateです))とか、ビューデバッガーの [Show Constraints] 機能とか、知らなかったことが色々と書いてありました。


##まとめ

書籍『よくわかるAuto Layout』を紹介させていただきました。Auto Layoutがよくわかってない人を対象として書かれた書籍ですが、<b>中級者にも勉強になる部分は多い</b>と感じました。


本をまるっと一冊通読してAuto Layoutを勉強するというのはなかなか難しい、と感じる方もいらっしゃるかもしれません。が、目次を見れば分かる通り、Auto Layoutについてかなり網羅的かつ本質的に解説されてますので、リファレンス的に手元に置いておくのもいいのでは、と思います。


気になった方はぜひ！


<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4865940324/22301-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/51ELGPlwjgL._SL160_.jpg" alt="よくわかるAuto Layout  iOSレスポンシブデザインをマスター" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4865940324/22301-22/ref=nosim/" name="amazletlink" target="_blank">よくわかるAuto Layout  iOSレスポンシブデザインをマスター</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 16.07.17</div></div><div class="amazlet-detail">川邉 雄介 <br />リックテレコム <br />売り上げランキング: 14,747<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4865940324/22301-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jpで詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>