Xamarin.iOSでAutoLayoutをコードから書く際に便利なライブラリ

#はじめに

本記事は[Xamarin Advent Calendar 2018](https://qiita.com/advent-calendar/2018/xamarin)の10日目として、Xamarin.iOSでAutoLayoutをコードから書く際に便利なライブラリを紹介します。

# iOSアプリ開発でのユーザインタフェースの作成

皆さんはiOSアプリ開発で、どのようにユーザインタフェースを作成していますか。
StoryboardをXcodeで編集する際は[Interface Builder](https://developer.apple.com/jp/documentation/ToolsLanguages/Conceptual/Xcode_Overview/BuildingaUserInterface/UsingInterfaceBuilder.html)、Visual Studioで編集する場合は[iOS Designer](https://docs.microsoft.com/ja-jp/xamarin/ios/user-interface/designer/?tabs=windows)を使っているのではないでしょうか。

<img width="1018" alt="iOS Designer" src="https://qiita-image-store.s3.amazonaws.com/0/146488/4a03fbb0-327a-43b9-c970-a56bc69edb63.png">

## Storyboardを使うデメリット

Storyboardを使う開発では以下のようなデメリットがあると認識しています

* チーム開発においてGitのコンフリクトがほぼ確実に発生して、XMLを編集するよりInterface Builderで作り直したほうが良いレベル
* Dependency Injection（Initializer Injection）ができない（Stotyboardではなくxibなら可）
* ソースコードとの関係性が良く分からない

Gitのコンフリクトは深刻な問題で、「一画面一Storyboard」とか「Storyboardを編集する人は一人のみ」などで運用しているチームもあると聞きます。

## Storyboardを使わず、ソースコードでユーザインタフェースを作成する

Storyboardにデメリットを感じ、ソースコードでユーザインタフェースを作る方法を採用する人もいます。
Microsfot Docsにも「[Xamarin.iOS でのコードで iOS ユーザー インターフェイスの作成](https://docs.microsoft.com/ja-jp/xamarin/ios/app-fundamentals/ios-code-only?tabs=macos)」という説明ページがあります。

## Auto Layoutをソースコードで書くと

Viewの位置をAutoLayoutで書くと以下のようになります。

```C#
translatedLabel.HeightAnchor.ConstraintEqualTo(20).Active = true;
translatedLabel.CenterXAnchor.ConstraintEqualTo(View.CenterXAnchor).Active = true;
translatedLabel.TopAnchor.ConstraintEqualTo(translateButton.BottomAnchor, 20).Active = true;
translatedLabel.LeftAnchor.ConstraintEqualTo(View.LayoutMarginsGuide.LeftAnchor).Active = true;
translatedLabel.RightAnchor.ConstraintEqualTo(View.LayoutMarginsGuide.RightAnchor).Active = true;
```
この量でViewの1部品です。
一つの画面はいくつものViewの集合によるもので、制約はたくさんありますよね。
以下は翻訳アプリの画面構成例とその制約です。

![制約例.PNG](https://qiita-image-store.s3.amazonaws.com/0/146488/1234f56d-31b9-7483-f6fd-b1f95547c7f0.png)

## もっと簡潔に書きたい

AutoLayoutのコーディングを支援するライブラリがあります。

* Cirrious.FluentLayout
  * https://github.com/FluentLayout/Cirrious.FluentLayout
* Masonry
  * https://github.com/xamarin/XamarinComponents/tree/master/iOS/Masonry
* PureLayout.Net
  * https://github.com/mallibone/PureLayout.Net
* SnapKit.Xamarin
  * https://github.com/Tylerian/SnapKit.Xamarin 

Xamarin.iOSに対応した支援ライブラリの中ではCirrious.FluentLayoutが一番使われているようです。
Cirrious.FluentLayoutを使うと先ほどのコードが以下のように書けます。

```C#
View.AddConstraints( 
  translatedLabel.Height().EqualTo(20),
  translatedLabel.WithSameCenterX(View),
  translatedLabel.AtTopOf(translateButton, 20),
  translatedLabel.ToLeftMargin(View),
  translatedLabel.ToRightMargin(View)
);
```
だいぶ見やすくなったのではないでしょうか。

## AutoLayoutをコードで書く際の注意点

* UIKit のAPIの仕様変更時にコードの修正が必要
  * Interface Builderを使っていたら自動で対応できることが多い
     * ただし支援ライブラリがすぐに対応してくれると負担は減る
* AutoLayoutの制約違反が実行時にしか分からない
  * Interface Builderを使っていたら編集時に分かる
* 支援ライブラリの更新が止まるリスク

# その他：Objective-C/Swiftで使える支援ライブラリ

Objective-C/Swift向けの支援ライブラリは色々とあります。

* [roberthein/TinyConstraints](https://github.com/roberthein/TinyConstraints)
* [nakiostudio/EasyPeasy](https://github.com/nakiostudio/EasyPeasy)
* [SnapKit/SnapKit](https://github.com/SnapKit/SnapKit)
* [PureLayout/PureLayout](https://github.com/PureLayout/PureLayout)
* [robb/Cartography](https://github.com/robb/Cartography)
* [freshOS/Stevia](https://github.com/freshOS/Stevia)
* [Raizlabs/Anchorage](https://github.com/Raizlabs/Anchorage)

私がSwiftでコーディングする際は[TinyConstraints](https://github.com/roberthein/TinyConstraints) を使っています。


以上です。