OnBoardというライブラリを使ってみた

仕事で[OnBoard](https://github.com/mamaral/Onboard)というライブラリを使って実装したので、OnBoardについて書こうと思います。

※この記事中にはOnBoardのREADMEに書かれているコードを多用させていただいてます。

# OnBoard系ライブラリ比較

OnBoardを作るにあたっていくつかのライブラリを検討したので表にまとめます。

| ライブラリ名 | スター数 | 最新コミット |インストール|
|:--|:--|:--|:--|
|[JazzHands](https://github.com/IFTTT/JazzHands)|5,797|1年以内|CocoaPods|
| [OnBoard](https://github.com/mamaral/Onboard)  | 4,133  |  1ヶ月以内 |CocoaPods|
| [EAIntroView](https://github.com/ealeksandrov/EAIntroView)  |  3,102 |  1週間以内 |CocoaPods|
|[MYBlurIntroductionView](https://github.com/MatthewYork/MYBlurIntroductionView)|1,472|2年以内|CocoaPods|
|[paper-onboarding](https://github.com/Ramotion/paper-onboarding)|1,417|3ヶ月以内|CocoaPods, Carthage|
|[ICETutorialSwift](https://github.com/icepat/ICETutorialSwift)|11|2年以内|？|
※スター数、最新コミットは執筆時時点の状況です。

**JazzHands**はスター数が多くページ遷移のアニメーションも素晴らしいのですが、今回はここまでの機能は必要なかったので採用を見送りました。今度個人的にいじってみたいです。
**OnBoard**はスター数が多くコミットもされており、それなりにカスタマイズしやすそうだったので採用しました。
**EAIntroView**もスター数が多くコミットもされていたのでOnBoardと迷ったのですが、OnBoardの方がカスタマイズしやすそうな印象を受けたのと、スター数を考慮して結局こちらは見送りました。個人的にはちょっと触ってみたいです。
**MYBlurIntroductionView**に関しては「iOS6と7に互換性があります」と書かれていて、「あれ？iOS8以降は...？？」となったので選択肢から除外しました。
**paper-onboarding**は[この前いじってみて](http://qiita.com/akatsuki174/items/49f48e3c353e8e144d36)勝手がわかっていますし簡単に実装できるので良いなぁとは思ったのですが、ページ遷移時に発生するアニメーションは必要ないので削る作業が発生しますし、OnBoardの方が圧倒的にスター数が多かったので今回は使いませんでした。
**ICETutorialSwift**はスター数が少なくライブラリ作者の方がここ半年くらいGitにコミットしていないので不安になって採用を見送りました。

# OnBoardの概要

使うクラスは`OnboardingViewController`と`OnboardingContentViewController`の2つです。OnboardingContentViewControllerに画像、タイトル、説明文、ボタン文言などの1ページの要素をセットして、それをOnboardingViewControllerに詰め込んで使う形になります。

```swift
// 1ページ分のVC作成
let firstPage = OnboardingContentViewController(title: "Page Title", body: "Page body goes here.", 
                                                image: UIImage(named: "icon"), buttonText: "Text For Button") { () -> Void in
    // do something here when users press the button, like ask for location services permissions, register for push notifications, connect to social media, or finish the onboarding process
}

// 各ページのベースとなるVC作成
let onboardingVC = OnboardingViewController(backgroundImage: UIImage(named: "background"), contents: [firstPage])
```

ここでは1ページ分しか入れてませんがご覧の通り`contents`にはOnboardingContentViewControllerの配列を渡せるので何ページでも入れられます。
また、OnboardingViewControllerを生成する時に背景画像を渡していますが、代わりに動画を渡すこともできます。

# OnBoardでできること

## マージンのカスタマイズ

![OnBoard.png](https://qiita-image-store.s3.amazonaws.com/0/100736/dada3e26-8d7c-84bb-e0ba-29fafd0ceb94.png)
※OnBoardのREADMEの画像です。

```
onboardingVC.topPadding = 20
```

などとすることによってマージンの調整をすることができます。

## 画像効果

背景画像に対してブラー、マスキング、フェードなどの効果を付けることができます。

## ナビゲーションのカスタマイズ

まずボタンについてです。デフォルトでページ下についているボタンは普通のボタン（例えばアラートが表示されるなど）として使うこともできれば、次のページに遷移するボタンとしても使うことができます。次のページに遷移するボタンとして使う場合は以下のコードを挿入します。

`contentVC.movesToNextViewController = true`

その他にもスワイプでの遷移をできなくしたり、ページコントロールを隠したりすることができます。

## スキップ

OnBoardの途中のページでスキップを可能にしたり、スキップ時のイベントを設定することができます。

```swift
onboardingVC.allowSkipping = true
onboardingVC.skipHandler = {
  // スキップ時のイベント
}
```

スキップ時のイベントとしては「アプリの使い方は◯◯から再度確認することができます」というアラートを表示すると親切ですね。

## ブロック

ページのviewWillAppear, viewDidAppearのタイミングでイベントを発生させることもできます。

```swift
contentVC.viewWillAppearBlock = {
    // do something when the view will appear here…
}

contentVC.viewDidAppearBlock = {
    // do something when the view appears here…
}
```

# OnBoardでできないこと、不便なこと

## 背景画像を1ページごとに変える

[issue#108](https://github.com/mamaral/Onboard/issues/108), [issue#71](https://github.com/mamaral/Onboard/issues/71)でも書かれている通り、基本的にはこのライブラリでは背景画像を1枚しか設定できず、どのページでも同じ背景画像になってしまいます。
ただissue#71では「頑張ったら背景画像設定できた」と言っている人がいるので、ページごとに背景画像を変えようと思えば変えられるようです。

## 細かなレイアウト調整

先程のマージン説明の画像を見ればわかるのですが、title部分とbody部分の間にはpaddingがないのでtitleやbodyの高さが膨らんだときにはbodyがボタンの下に隠れるという自体が発生します。また、AutoLayoutで書かれているというわけではなく、中のコードを見てみると下記のようになっているのでレイアウトの仕方によってはこのライブラリだとキツイ気がします。

```objc
[self.iconImageView setFrame:CGRectMake((viewWidth / 2.0) - (self.iconWidth / 2.0), 
self.topPadding, self.iconWidth, self.iconHeight)];
```

とりあえず今回の導入に当たってはレイアウトが崩れないようにラベルの高さを固定して、文字が多くなったとしてもこの高さからはみ出ないようにフォントサイズを縮めていくという策を取りました。

## 横画面でのOnBoard表示

READMEに書かれていますが、現在横画面はサポートしていないようです。自分でコードを書き足す必要があります。

## Xcode8, Swift3.0でクラッシュ（執筆時点）

このライブラリ採用当時はこのissueは上がっていなくて気づいていなかったのですが、バージョンを挙げるとクラッシュするというissueが上がっていました。
https://github.com/mamaral/Onboard/issues/150
ただプルリクを送って下さる方が現れているので、もう少しすればバージョンを上げてもクラッシュしないようになるのではないかと思います。

# 使ってみた感想

かなり楽にOnBoardが作れたのが良かったです。難しくて躓いたというところはなかったような気がします。サンプルコードもスキップやブロックが使われていてどのようなことができるのがかすぐにわかり、大いに参考になりました。
ただ上記に上げたデメリットもあるので、OnBoardのライブラリ選定をするのであればこのデメリットを踏まえた上で検討すべきかなと思います。