楽にOnBoarding画面を作れるライブラリ、paper-onboardingについて

Swiftで使えるライブラリを見ていく中でOnBoarding画面が楽に作れちゃうものがあったので紹介しようと思います。

# そもそもOnBoardingとは

IT用語辞書では「組織やサービスに新たに加入した人に手ほどきを行い、慣れさせること」と書かれています。なのでアプリにおいては「初めてアプリを使う人に対してこのアプリがどのようなものなのかを説明し、慣れてもらうこと」と言えるかなと思います。チュートリアルもこれに当たると思います。

# OnBoardingの重要性

なぜOnBoardingが重要なのかは[この記事](https://growthhackjournal.com/retention/80-20-onboarding)にたっぷり書かれているので簡略化しますが、主立ったところで言うと、新規ユーザがそのアプリを継続的に使用してくれるかを左右しかねないので重要、ということです。

# 今回紹介するライブラリ：paper-onboarding

そこで今回紹介するのが[paper-onboarding](https://github.com/Ramotion/paper-onboarding)というライブラリになります。完成イメージ図はpaper-onboardingのGitHubのGifを見ていただくと良いと思いますし、Gitにデモプロジェクトが挙がっているので落として動かしてみるといいと思います。

画面の構成はざっくり言うと以下のようになっています。
![スクリーンショット 2016-08-14 12.46.52.png](https://qiita-image-store.s3.amazonaws.com/0/100736/67fed93f-1269-da34-429e-dc2862d9e429.png)

推奨環境はiOS8.0以上、Xcode7.3、ライセンスはMIT、スター数は1357、つい最近もコミットされておりまだまだ進化する可能性のあるライブラリだと思います。

それではこれから実装手順について説明したいと思います。一応お断りをしておくと、あくまで実装の一例なので他の方法でできないわけではないです。

ちなみに執筆時に使用しているpaper-onboardingのバージョンは1.1.3です。

# インストール

最初Carthageでやろうとしたのですが素直に出来なかったので、CocoaPods（バージョン1.0.1）で入れることにしました。`pod 'paper-onboarding'`をPodfileに記述するだけでOKです。CocoaPods自体の使い方が不安な人は[ここ](http://qiita.com/ShinokiRyosei/items/3090290cb72434852460)などを参考にしてください。

ちなみに後々SwiftGenを使うことになるので、SwiftGenをCocoaPodsで入れたい人はこのタイミングで入れておくと良いです。私はSwiftGenをHomebrewで入れたのでここではpaper-onboardingだけインストールしました。

# PaperOnboardingを継承したUIViewを作る

Gitにある通り、以下のコードをUIViewControllerに記述しました。

```swift:UIViewController.swift
override func viewDidLoad() {
  super.viewDidLoad()

  let onboarding = PaperOnboarding(itemsCount: 3)
  onboarding.dataSource = self
  onboarding.translatesAutoresizingMaskIntoConstraints = false
  view.addSubview(onboarding)

  // add constraints
  for attribute: NSLayoutAttribute in [.Left, .Right, .Top, .Bottom] {
    let constraint = NSLayoutConstraint(item: onboarding,
                                        attribute: attribute,
                                        relatedBy: .Equal,
                                        toItem: view,
                                        attribute: attribute,
                                        multiplier: 1,
                                        constant: 0)
    view.addConstraint(constraint)
  }
}
```

今回はOnBoardingを3枚用意しようと思うので`PaperOnboarding`のitemsCountは3にしています。

# 画像を用意する

OnBoardingで使用する画像を準備します。用意しておいた方がいい画像はメイン画像3枚、アイコン3枚になります。とりあえず適当なサイズの画像を当てても大丈夫ですが、正確に言うとメイン画像188*188、アイコン画像30*30が最適かと思います。
![スクリーンショット 2016-08-12 22.15.38.png](https://qiita-image-store.s3.amazonaws.com/0/100736/fabfd07b-f6ec-7c7a-347e-97db7a7b398b.png)
メイン画像を指定しなかった場合はメイン画像のスペースが背景色が広がっている状態、アイコン画像を指定しなかった場合は以下の画像のようにただの丸が表示されます。
![スクリーンショット 2016-08-12 22.26.33.png](https://qiita-image-store.s3.amazonaws.com/0/100736/5a9baa17-bca8-460c-279d-bd50316d3ec2.png)

# 画像をAsset Catalogに入れる

言葉通りです。作ってください。

# Asset CatalogのEnumを作る

CocoaPodsでSwiftGenを入れていない人は以下のコマンドを打ってSwiftGenをインストールしてください。

```
$ brew update
$ brew install swiftgen
```

Asset CatalogのEnumの作り方については[How to Use SwiftGen to Generate an Enum From Your Asset Catalog](http://blog.metova.com/how-to-use-swiftgen/)という記事を参考にしました。このページの「Step-by-step guide」の手順を辿れば作れます。あえて注意点を挙げるとすれば、「次のスクリプトを追加してね」という手順があるのですが、「次のスクリプト」に当たる部分が意外と長いので最後までコピペしてね、ということです。説明文だけでなくGifを見ながらやれば特に引っかからないと思います。

# DataSourceを用意する

Gitに書かれている通り、以下のように指定します。

```swift
func onboardingItemAtIndex(index: Int) -> OnboardingItemInfo {
   return [
     ("BIG_IMAGE1", "Title1", "Description text1", "IconName1", "BackgroundColor", textColor, DescriptionColor, textFont, DescriptionFont),
     ("BIG_IMAGE2", "Title2", "Description text2", "IconName2", "BackgroundColor", textColor, DescriptionColor, textFont, DescriptionFont),
     ("BIG_IMAGE3", "Title3", "Description text3", "IconName3", "BackgroundColor", textColor, DescriptionColor, textFont, DescriptionFont)
   ][index]
 }

func onboardingItemsCount() -> Int {
  return 3
}
```

OnboardingItemInfoは

```
(imageName: String, title: String, description: String, iconName: String, color: UIColor, 
titleColor: UIColor, descriptionColor: UIColor, titleFont: UIFont, descriptionFont: UIFont)
```

となっているので、例えばimageNameのところには先ほど作ったAssetのEnumを使って`Asset.Image1.rawValue`という形で指定します。

あとはよろしく文章や色、フォントをセットしてください。

# delegate

上記までの準備をすれば最低限のものはできていると思いますが、もうちょっと手を加えたいときは3つのdelegateがあるのでこれを活用します。

* `onboardingWillTransitonToIndex(index: Int)`
    * スクロールがスタートした時点で呼ばれます。デモプロジェクトでは「skip」ボタンの表示 / 非表示をここでコントロールしています。
* `onboardingDidTransitonToIndex(index: Int)`
    * 指定したindexが選択状態になった時に呼ばれます。
* `onboardingConfigurationItem(item: OnboardingContentViewItem, index: Int)`
    * itemの要素が描画されるタイミングで呼ばれます。itemに関する設定を行いたい場合はここでやります。

# おまけ：カスタマイズ

## ラベルの背景色を変える

READMEに書かれている通り、ContentViewのItemの設定をいじりたいときはonboardingConfigurationItemメソッド内で行います。この時、viewDidLoadで`onboarding.delegate = self`を`onboarding.dataSource = self`より前に記述することを忘れないでください。

```swift
func onboardingConfigurationItem(item: OnboardingContentViewItem, index: Int) {
  item.titleLabel?.backgroundColor = .redColor()
  item.descriptionLabel?.backgroundColor = .redColor()
}
```

## メイン画像のサイズを変える

メイン画像が貼り付いているImageViewの大きさについてですが、ライブラリ内の `OnBoardingContentViewItem.swift` で指定されています。以下の部分です。

```swift:OnBoardingContentViewItem.swift
for attribute in [NSLayoutAttribute.Width, NSLayoutAttribute.Height] {
  imageView >>>- {
    $0.attribute = attribute
    $0.constant  = 188
  }
}
```

なので大きさを変えたい場合は例えば上記の188を好きな数字に変えたり、以下のようにonboardingConfigurationItemメソッド内で変えたりします。

```swift
func onboardingConfigurationItem(item: OnboardingContentViewItem, index: Int) {
  for constraint in item.imageView!.constraints {
    if constraint.firstAttribute == .Width {
      constraint.constant = 320
    }
    if constraint.firstAttribute == .Height {
      constraint.constant = 320
    }
  }
}
```

# 所感

上記の手順通りにやればおそらく1時間程度でできるので、ほんの少しの労力でキレイなOnBoardingを作れるという点では非常に良いライブラリだと思います。ただカスタマイズしようと思うとちょっと使いづらいかもしれません。