UIを作る際にライブラリにする？それともDIYする？の切り分けと実装のアイデア帳 (@Swift Tweets 2018 Spring)

# UIを作る際にライブラリにする？それともDIYする？の切り分けと実装のアイデア帳

こちらの内容は[Swift Tweets 2018 Spring](https://swift-tweets.github.io/2018-spring)で発表させて頂きました「UIを作る際にライブラリにする？それともDIYする？の切り分けと実装のアイデア帳」の内容に少し加筆したものなります。

+ [私の発表ツイートの一覧（スレッド形式になっております）](https://twitter.com/fumiyasac/status/985143513502253056)
+ [Swift Tweets 2018 Springに関するTogetter](https://togetter.com/li/1218153)

## 1. はじめに

Swift自体はSwift1系の時から趣味で嗜むことから始めて、2017年からiOSエンジニアとなりました。

これまでのキャリアから始めて、デザイナー → サーバーサイドエンジニア → iOSやReactNative等をするようになったこともあって、UI周りの実装に関するTIPS等を僭越ながら取り組んだり登壇したりしています。

今もiOSに関するトピックの中で一番好き＆関心がある部分はUI表現に関することです。
新しいアプリや話題になっているアプリのUI実装を調べたり、体感やアニメーション等のUXを考察すること自体は今でも楽しみの一つです。

現在の業務におきましても、このようなUI表現に関する実装部分を担当する機会も多々あったり、デザイナーの方との共同で作業を進めていく上でも色々と活かせる機会があったことに関しては非常に幸運であったと感じています。

## 2. DIY(自作)するか？それともライブラリを使おうか？という判断

それでは、本題に入っていきたいと思います。
UI構築していて、この動きはDIY(自作)するか？それともライブラリを使おうか？という判断に迷うなぁ、と感じてしまうことはないでしょうか？

この部分の判断は一概に「これが良い！」とは断言しにくい部分ではあると思いますし、開発しているプロダクトの規模等によっても変わってくると思います。
ですので今回ではどれが良いかという結論はあえて出さずに「それぞれのケース」をご紹介できればと思います。

※ この記事で紹介しているもの以外で、便利な実装やライブラリをご存知の方がいらっしゃいましたらメンション等を頂けますと嬉しく思います！

まず前段として、DIY(自作)するか？それともライブラリを使おうか？という判断においてそれぞれの場合のメリットとデメリットを簡単に表としてみました。

![capture0.jpg](https://qiita-image-store.s3.amazonaws.com/0/17400/3f65ec2b-db12-50d9-79d5-c6b5c8034eb6.jpeg)

後から「思っていたのと違う！」とならない様に最初に使いたいライブラリの検証や下調べを行なったりすると良いと思います。

（余談）漠然とやってみたいんだけど画面単位での設計が詰め切れてないような場合には、「手書きで図解をまとめて」イメージができる状態から議論できるように心がけております。

## 3. 要件の複雑さによっては自前で実装するよりもライブラリを活用しても良さそうな例

ここからは具体的な例をあげて、ご説明ができればと思います。
このようなUIを構築する際の具体例やライブラリの紹介をしていきます。

__ケース1：星型Ratingを表示するようなUI__

最初は、星型Ratingを表示するようなUIを考えてみたいと思います。

<img width="400" alt="case1例.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/c1008dc1-9dd8-4a6d-08d5-8633701d7806.png">

1〜5までの整数値の表示の場合ならば、自作をする選択をしても実装はできそうですね。
しかしながら2.5を選択した際は星マークを半分にしたり、星2.7とした時は星マークの塗りつぶしを7割にしたい場合までは、この形では少し難しいかもしれません。

<img width="400" alt="case1図解その1.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/56846cb7-8f8c-07db-7c41-706b3a5514b9.png">

このような要望に対応してみるために、今回はこの部分の実装をうまくやってくれそうなライブラリを活用してみました。

+ [ライブラリ: Cosmos](https://github.com/evgenyneu/Cosmos)

導入と実装方法に関しては、こちらの図解のような形になります。

<img width="773" alt="case1図解その2.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/a58fda4c-1085-6cde-1a5e-8f0382778935.png">

このライブラリに関しては表示や入力のユースケースにも対応していたり、IB上での調整の考慮等も含めて自分でもカスタマイズするための余地があるライブラリなので使い勝手も良さそうですね。

__ケース2：Twitterのハッシュタグみたいな表現やテキストの中にリンクがある様な感じのUI__

次にTwitterのハッシュタグみたいな表現やテキストの中にリンクがある様な感じの表現を考えてみましょう。

<img width="400" alt="case2図解その1.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/e737f791-419d-bd52-46b3-82a33fa7e3a6.png">

Webサイトのaタグが一部だけ仕込まれているテキストの様な表現を実現する場合も、元々はUILabelやUITextViewのテキストで作られていた部分に、あとからハッシュタグとURLリンクが欲しいというような要望が出てきた場合、この状態のままでは一筋縄でいかない部分かもしれません。

このような要望に対応してみるために、今回はこの部分の実装をうまくやってくれそうなライブラリを活用してみました。

+ [ライブラリ: ActiveLabel](https://github.com/optonaut/ActiveLabel.swift)

導入と実装方法に関しては、こちらの図解のような形になります。

![case2図解その2.png](https://qiita-image-store.s3.amazonaws.com/0/17400/b2098087-b007-b11b-ebf8-ca9f48b5229d.png)

このライブラリも、ハッシュタグ・メンション・URLへの対応と併せて自分でタグを定義したりすることもできる感じこちらもなかなか良さそうですね。

__ケース3：メディアアプリの記事詳細画面のような画面のUI__

もう一つ、メディアアプリでもよくお目にかかる記事詳細の画面のような形の表現を考えてみましょう。

下の図解であるような画面をライブラリを使用せずに自作する場合、NavigationBar部分のカスタマイズを伴って複雑な動きまで実装が必要な場合においては、
それぞれのViewの重なりと動きにも留意せねばいけないので、自作するとなかなか難しい部分ではないかと思います。

<img width="1343" alt="case3図解.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/d1c0d289-4192-e9db-1953-b07d30eccbd2.png">

もしそこまで複雑な動きが必要ないのであれば、下記のようなライブラリを活用した実装をするのも一つの手段かと思います。

+ [ライブラリ: ParallaxHeader](https://github.com/romansorochak/ParallaxHeader)

ここからは補足になりますが、ライブラリを使用しないで実装する場合には[私が行なったライブラリを用いずに類似した実装を行なった際の例](https://qiita.com/fumiyasac@github/items/d1b56ffc6d7d46c0a616#5-%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E7%B3%BB%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E8%A8%98%E4%BA%8B%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%A7%E3%82%88%E3%81%8F%E8%A6%8B%E3%82%8B%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E7%94%BB%E5%83%8F%E3%82%84%E5%8B%95%E3%81%8F%E3%83%8A%E3%83%93%E3%82%B2%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%90%E3%83%BC%E9%83%A8%E5%88%86%E3%81%AEui%E6%A7%8B%E6%88%90%E3%81%A8%E5%AE%9F%E8%A3%85%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E8%A7%A3%E8%AA%AC)のような形でも実装することも可能ですし、実装方法や表現については様々なバリエーションがあるかと思います。形作るView要素の関係が複雑になる程デバッグが大変になってしまうこともあるのでその点に留意すると良いかと思います。

__補足：AnimationやCustomTransitionの際に活用できそうなライブラリの紹介__

これから紹介するライブラリに関しては、アニメーションやカスタムトランジションに対してのアプローチをしやすくするためのライブラリの例になります。
IB上で設定できるようになるものもあるので、少し好みが別れてしまうかもしれませんが参考になれば幸いです。

こちらはアニメーションに関するライブラリの一例になります。

| ライブラリ名 | ライブラリの機能概要 |
|:-----------|:------------|:------------|
|[ライブラリ: IBAnimatable](https://github.com/IBAnimatable/IBAnimatable) |アニメーションの処理をIntefaceBuilder上で扱い易くするライブラリ |
|[ライブラリ: ViewAnimator](https://github.com/marcosgriselli/ViewAnimator) |Animationの処理をコード記載を扱い易くするライブラリ |

こちらはカスタムトランジションに関するライブラリの一例になります。

| ライブラリ名 | ライブラリの機能概要 |
|:-----------|:------------|:------------|
|[ライブラリ: Hero](https://github.com/lkzhao/Hero) |様々なバリエーションのCustomTransitionを提供するライブラリ |

## 4. そのほかUI表現の実装においてライブラリを活用するか否かを考えそうなケースの例

ここからは、そのほかUI表現の実装においてライブラリを活用するか否かを考えそうなケースについても考えてみることにしましょう。
紹介する例としましては下記の3つの事例に関する紹介になります。

+ カレンダーを実装するライブラリの紹介
+ ステップインジケーターを実装するライブラリの紹介
+ UICollectionViewを拡張したライブラリの紹介

__ケース1：カレンダー実装をしたい場合の例__

カレンダー実装をしたい場合のUI表現を考えてみましょう。
カレンダーのUIに関しても添付した図で掲載している様なシンプルなものであれば、UICollectionView等をうまく活用することで実現はできるかと思います。

<img width="400" alt="case5例.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/909a7f08-92df-7d3c-ad76-546679e4393d.png">

カレンダーのUIでは添付したメモの記載でもあるように、デザインやUIとのさじ加減と合わせて、「どのようなデータを表示しどのような機能を実現するのか？」という観点での考慮を行なった設計が必要な部分なので、要件が複雑になると頭を抱えてしまいそうですね。

![case5設計メモ.png](https://qiita-image-store.s3.amazonaws.com/0/17400/5da16a9b-4e28-7a64-7bd2-c56961fac630.png)

こちらはカレンダーに関するライブラリの一例になりますが、必要な機能に合わせて自作するような場合でも中のコードを参考に構築するような方針で進めてみても良いかと思います。

+ [ライブラリ: JTAppleCalendar](https://github.com/patchthecode/JTAppleCalendar)
+ [ライブラリ: JBDatePicker](https://github.com/Tuslareb/JBDatePicker)

__ケース2：ステップインジケーターを実装をしたい場合の例__

次はステップインジケーターを実装をしたい場合のUI表現を考えてみましょう。
こちらに関してもインジケーターの動きや形状・デザイン表現によっては、自作するか否かの判断をしなければいけないこともあるかもしれません。

<img width="400" alt="case6例.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/17edd571-2457-a6f8-1658-8295362a358e.png">

ここでは2つ程ステップインジケーターの様な表示をするためのライブラリの例を、主な特徴も含めまして簡単に紹介していきたいと思います。

+ [ライブラリ: FlexibleSteppedProgressBar](https://github.com/amratab/FlexibleSteppedProgressBar)

__このライブラリの主な特徴:__

1. InterfaceBuilderでも色の変更やインジケーター個数が簡単にできる
2. FlexibleSteppedProgressBarDelegateプロトコルになっている (イメージとしてはUIPageViewControllerの様な感じに近いです)

+ [ライブラリ: KYNavigationProgress](https://github.com/ykyouhei/KYNavigationProgress)

__このライブラリの主な特徴:__

1. こちらはNavigationBar直下にインジケーターを表示するシンプルなもの
2. InterfaceBuilderベースではないが自作のUIとも合わせやすい印象

__ケース3：UICollectionViewを拡張したUIを実装をしたい場合の例__

最後にUICollectionViewを用いた表現をするライブラリの事例を紹介させていただければと思います。
添付した図のようなカバーフロー型の動き方やセルが重なる動き方は下記のライブラリで実現できます。

<img width="400" alt="case7図解.png" src="https://qiita-image-store.s3.amazonaws.com/0/17400/0f1676ee-1f7d-ce2d-a226-e222b13a5348.png">

__その1. Finderの様な写真ギャラリー風のUIを作成__

+ [ライブラリ例1: iCarousel (Objective-C)](https://github.com/nicklockwood/iCarousel)
+ [ライブラリ例2: FSPagerView (Swift4対応)](https://github.com/WenchaoD/FSPagerView)

__その2. セルを上へスクロールすると前のセルに重なる動き__

+ [ライブラリ例: VegaScrollFlowLayout (Swift4対応)](https://github.com/AppliKeySolutions/VegaScroll)

## 5. あとがき

今回は割と表現に関する事例の紹介やライブラリの紹介が多くなりましたが、自作するかライブラリを使うかの判断に関しては、どちらを選択するかの決め手は設計はもちろんプロジェクトの事情等により変化するものなので、一つに決めるのは難しい部分かと思います。

UIライブラリを使う時は、実現したい表現や仕様にそぐうか？という観点はもちろんですが使いやすさ・拡張の余地があるか？という観点を持った上で選ぶとより良い選択ができるのではないかと思います。

最後になりますが「Swift Tweets」の運営者の皆様、そして発表してくださった方々や参加してくださった皆様、本当にありがとうございました！