アプリを初めて起動したときに画面の使い方を教えてくれるコーチマークを実装

# コーチマークとは

よくアプリを初めて起動したときに、画面の機能を紹介してくれるものです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94929/78cc8b9d-6d67-c9b2-4ddc-2bbb4891686b.png" height="500" style="height: 500px;"/>

こういう感じに使い方を教えてくれます。

機能が多くなると、どうしてもUIが複雑になります。
そうすると、初めて触るユーザーは困惑してしまうかもしれません。
できるだけ、説明しなくても扱えるように設計するのが最善なのでしょうが、そうは言ってられないこともありますからね。
コーチマークを付ければ、初めて使うユーザーでもどのボタンを押せば何が起こるのかが、わかりやすくなります。

# ライブラリをインストール

いろいろあるのですが [ephread/Instructions](https://github.com/ephread/Instructions) を使ってみました。

```:Podfile
pod 'Instructions'
```

```shell
$ pod install
```

`Podfile` にライブラリを追加してターミナルで `pod install` を実行しましょう。
以上でインストールは終わりです。

# 実装

では、ライブラリを使ってコーチマークを表示してみましょう。

`CoachMarksController` のインスタンスを作って、`dataSource` を設定します。
今回は全部 `ViewController` で行ってますが、別クラスに分割してもいいと思います。

```swift:ViewController.swift
import Instructions

class ViewController: UIViewController, CoachMarksControllerDataSource {
    var coachController = CoachMarksController()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.coachController.dataSource = self
    }
}
```

次に `CoachMarksControllerDataSource` のメソッドを実装します。
最低限必要なのは、

* マークの数を返す `numberOfCoachMarks(for coachMarksController: CoachMarksController)`
* マークの座標を設定する `coachMarksController(_ coachMarksController: CoachMarksController, coachMarkAt index: Int)`
* 表示する文章を設定する `coachMarksController(_ coachMarksController: CoachMarksController, coachMarkViewsAt index: Int, madeFrom coachMark: CoachMark)`

でしょうかね。

```swift:ViewController.swift
class ViewController: UIViewController, CoachMarksControllerDataSource {
    ...

    // コーチマークを表示したいUIView
    @IBOutlet weak var firstButton: UIButton!
    @IBOutlet weak var secondButton: UIButton!

    // マークのメッセージ配列
    private messages = ["First Message", "Second Message"]

    // UIViewを配列にしておきます
    private views = [self.firstButton, self.secondButton]

    func coachMarksController(_ coachMarksController: CoachMarksController, coachMarkViewsAt index: Int, madeFrom coachMark: CoachMark) -> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) {
        let coachViews = coachMarksController.helper.makeDefaultCoachViews(withArrow: true, arrowOrientation: coachMark.arrowOrientation)
        coachViews.bodyView.hintLabel.text = self.messages[index] // ここで文章を設定
        coachViews.bodyView.nextLabel.text = "了解" // 「次へ」などの文章

        return (bodyView: coachViews.bodyView, arrowView: coachViews.arrowView)
    }
    
    func numberOfCoachMarks(for coachMarksController: CoachMarksController) -> Int {
        return self.messages.count
    }
    
    func coachMarksController(_ coachMarksController: CoachMarksController, coachMarkAt index: Int) -> CoachMark {
        return self.coachController.helper.makeCoachMark(for: self.views[index], pointOfInterest: nil, cutoutPathMaker: nil)
        // for: にUIViewを指定すれば、マークがそのViewに対応します
    }
}
```

最後に、`CoachMarksController` の `start` と `stop` を呼び出します。

```swift:ViewController.swift
class ViewController: UIViewController, CoachMarksControllerDataSource {
    ...

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        self.coachMarksController.start(in: .window(over: self))
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        self.coachMarksController.stop(immediately: true)
    }
}
```

# 動作を確認

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94929/8dbad1ae-2c77-5315-2192-049b9404e71e.png" height="500" style="height: 500px;"/>

実行するとこんな感じになります。（文章や画面が上記のコードとは違うのはご了承ください）

デフォルトでは、オーバーレイの色は白みたいです。
個人的には黒が好みかな。

`coachMarksController.overlay` から色を変えられます。

```swift
self.coachController.overlay.color = UIColor.init(hex: "000000", alpha: 0.3)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94929/1f781909-6b7b-beab-bfd5-136dc576d702.png" height="500" style="height: 500px;"/>

# 備考

今のままだと、画面を開くたびにコーチマークが表示されるので `UserDefaults` などを使い初めての起動かどうかをチェックしたほうがいいでしょう。