アプリ内バナーの実装・運用をできるだけ楽にする（Swift × microCMS）

# はじめに

アプリの規模が大きくなってくると、販促やお知らせ、チュートリアル導線などのためにアプリ内にバナーを表示したいケースが出てきます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/adf460c8-af90-4bd2-f8a7-ae9d004c837b.png" width="400">
*（↑こういう画像バナーのイメージです）*

バナー表示に必要なのは「画像」「タップ時の遷移先URL」とシンプルですが、それなりの頻度でバナーを更新することを考えると運用ができるだけ楽になるようにホスティングしたい気持ちになってきます。

私がこれまで作っていた個人アプリでは、

* JSONファイルを適当なサーバーに置く
* Firebaseなどを利用してそれ専用のAPIを作る

などとしていましたが、更新が大変だったり、APIの管理が面倒だったりとモヤる点も多く、もっと良いソリューションがあるのではないかと感じていました。

この記事ではmicroCMSというサービスを利用して、バナー表示をできるだけ簡単に実装・運用する方法について書いてみます。

# バナーを表示する

まずはアプリのバナー表示を実装します。

## 管理画面から情報を入稿

バナーの「画像」と「遷移先URL」を管理画面から入稿します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/f0692867-0af6-b84d-5205-f70909ef07cb.png)
上記のように入稿してみました。
画像もmicroCMSでホスティングできるので、別のファイルストレージに画像をアップロードする必要はありません。


## APIプレビューで確認

入稿した情報はアプリ側からAPI経由で取得することになります。
管理画面の「APIプレビュー」機能からリクエストを試せます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/1033d457-cfc1-4bdc-0b08-fff003dc6b0b.png)
ここでレスポンスを確認し、問題なければ上部に表示されているiOSのコードサンプルを例に実装します。

## アプリに組み込み

今回はサンプルとして、写真ギャラリーアプリのヘッダー部分にバナーを表示していきます。

```
struct ContentView: View {
    let client = MicrocmsClient(
        serviceDomain: "<YOUR_SERVICE_DOMAIN>",
        apiKey: "<YOUR-API-KEY>")

    @State var banner: Banner?

    var body: some View {
        VStack(alignment: .leading) {
            if let banner = banner {
                ImageView(url: banner.image.url)
                    .onTapGesture {
                        UIApplication.shared.open(banner.url,
                                                  options: [:],
                                                  completionHandler: nil)
                    }
            }
        }
        .onAppear { fetch() }
    }

    private func fetch() {
        client.get(
            endpoint: "banners") { result in
            switch result {
            case .success(let object):
                self.banner = Banner(dict: object as! [String: Any])
            case .failure(let error):
                print("[ERROR] ", error)
            }
        }
    }
}
```
メインの実装部分だけピックして記載していますが、起動時にバナーをmicroCMSから取得して表示する実装になっています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/a9de515c-c8f2-231c-99b1-70b8d9f3c8fb.png" width="320">
実行するとこのような感じ。バナー画像をタップすると入稿している「遷移先URL」を開きます。これでアプリの画面にバナーを実装することができました。


## バナーを更新する（運用）

内容を変更したい場合はmicroCMSの管理画面から情報を更新すればOKです。

今回は簡単のため画像+遷移先URLだけにしていますが、必要なフィールドを追加することで、iOS/Androidで配信するバナーを分ける、アプリのバージョンによって出し分けるなどのケースにも柔軟に対応できます。


# 運用を助けるmicroCMSの機能

実際にバナー運用をしていて便利だと思った機能をいくつか紹介します。

## 画像API

microCMSは画像向けCDNであるimgixと提携しており、柔軟なリクエストで画像を取得できます。（[公式ドキュメント](https://document.microcms.io/image-api/introduction)）

例えば以下のように画像URLの末尾に`?w=200`とつけると画像のwidthをリサイズして取得できます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/48c4077c-b300-db83-ced3-1a344c91d151.png" width="400">
モバイルは様々な画面サイズが存在し、最も大きなものに合わせて画像を用意するとiPhone SEなどの小さな端末では過剰な画像サイズになります。
画像APIを使って端末ごとの表示領域に合わせたサイズの画像を取得することで、データ通信量を抑え、表示パフォーマンスを向上させることができます。

## 入稿ワークフロー

microCMSにはレビュー機能というものがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/ca3da045-f399-ae1b-6fe7-1e302848cd8a.png)
*（ [microCMS公式ブログ](https://blog.microcms.io/review-request/)より引用）*

GitHubのPull Requestライクな機能でコンテンツ更新をレビューできる機能です。
例えばバナーの入稿は誰でもできて、オーナー権限を持った人だけが承認&公開できるようなワークフローを組むことができます。（個人アプリは一人で運用してるので使っていませんが）

## 柔軟な入力フィールド

ヘッドレスCMSはスキーマの型を柔軟に決められます。例えばバナーの「公開開始日」が追加で必要になった場合、**日時フィールド**を使うことになるでしょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10057/e962310f-762f-284e-ac35-b4d7900a9033.png" width="400">
日時フィールドだとカレンダーのUIが表示されています。フィールドに応じたUIで入力できるため入稿が簡単です。
JSONファイルを手動で管理していた時は日付の文字列を間違えないように入力していたので気持ち的に楽になり助かっています。


# まとめ

microCMSを使うとアプリ内バナーの運用が楽になった話を書きました。
これからバナー実装を考えている方の参考になれば幸いです。

# サンプルコード

あまり大した実装はしていませんが、こちらに置いています。
https://github.com/himaratsu/BannerSample