microCMS

SwiftUI × microCMSでiOSアプリにバナーを実装する

ひまらつ

この記事は公開後、1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちはひまらつです。

この記事ではiOSアプリにバナーを実装していきます。
microCMSでアプリ用のバナーの管理をすることで、入稿側も実装側もシンプルにバナー機能を実装することができます。

バナーとは下記のような、アプリの画面のヘッダーなどに画像で表示され、タップしてURLに遷移するものをイメージしています。

この記事では画面はSwiftUIで実装しますが、バナー取得など基本的な実装はUIKitを使っている場合も同じです。

管理画面からバナー用のAPIを作成する

はじめに、microCMSの管理画面からバナー用のAPIを作成しましょう。
(まだアカウントをお持ちでない方はこちらから作成できます。)

まずはAPI名エンドポイントを決めましょう。今回は「バナー」、「banners」として進めます。

APIの型はリスト形式を選択します。

APIスキーマはバナー画像遷移先URLの2つのフィールドを定義します。

以下のような画面が表示されたら定義は完了です。

「追加する」より早速バナーを入稿してみましょう。


入稿したいバナーの画像遷移先URLをセットします。
ここで、コンテンツIDをバナーを表示したい画面名(ここでは home )に変更しています。
コンテンツIDの変更は必須ではありませんが、後の実装でこのIDを指定してバナーを取得するため、わかりやすい名前にしておくのがオススメです。

バナーの定義ができました。
右上の「APIプレビュー」から実際のAPIのレスポンスを確認してみましょう。


APIレスポンスは以下のようになっていると思います。

{
    "id": "home",
    "createdAt": "2021-09-13T07:31:58.582Z",
    "updatedAt": "2021-09-13T07:31:58.582Z",
    "publishedAt": "2021-09-13T07:31:58.582Z",
    "revisedAt": "2021-09-13T07:31:58.582Z",
    "image": {
        "url": "https://images.microcms-assets.io/assets/9f54a34e853e4bee98b47ce18c0713f1/b85d6be1ed9040769ea81be8eb539bb6/banner.png",
        "height": 180,
        "width": 960
    },
    "url": "https://jamjamjamstack.connpass.com/"
}


バナーAPIを作ることができました。

iOSアプリからバナー情報を取得する

microCMS iOS SDKの準備

microCMS iOS SDKはSwift Package Manager(SPM)より入手できます。


SPMを用いたインストールの詳しい手順は以下のドキュメントを参考にしてください。
https://document.microcms.io/tutorial/ios/ios-top

構造体の準備

まずは先ほど定義したバナーの情報を格納するクラスを作ります。

import Foundation
import SwiftUI

struct Banner {
    let id: String
    let image: BannerImage
    let url: URL

    init(id: String,
         image: BannerImage,
         url: URL) {
        self.id = id
        self.image = image
        self.url = url
    }
    
    init?(dict: [String: Any]) {
        if let id = dict["id"] as? String,
           let imageDict = dict["image"] as? [String: Any],
           let image = BannerImage(dict: imageDict),
           let urlString = dict["url"] as? String,
           let url = URL(string: urlString) {
            self.id = id
            self.image = image
            self.url = url
        } else {
            return nil
        }
    }
}

struct BannerImage {
    let url: URL
    let width: Double
    let height: Double   

    init?(dict: [String: Any]) {
        if let urlString = dict["url"] as? String,
           let url = URL(string: urlString),
           let width = dict["width"] as? Double,
           let height = dict["height"] as? Double {
            self.url = url
            self.width = width
            self.height = height
        } else {
            return nil
        }
    }
}

構造体の定義と、JSONオブジェクトから初期化するためのイニシャライザを用意しています。

SDKを使ってAPIをリクエストする

microCMS SDKを使って定義したAPIからバナー情報を取得してみましょう。

BannerView というViewを用意してバナーの情報をしてみます。

import SwiftUI
import MicrocmsSDK

struct BannerView: View {
    let client: MicrocmsClient
   
    init() {
        self.client = MicrocmsClient(
            serviceDomain: "<YOUR_SERVICE_DOMAIN>",
            apiKey: "<YOUR_API_KEY>"
        )
    }

    @State var banner: Banner?

    var body: some View {
        Text(banner?.id ?? "Loading...")
            .padding(12)
            .navigationTitle("バナー")
            .navigationBarTitleDisplayMode(.inline)
            .onAppear {
                fetchBanner()
            }
    }

    private func fetchBanner() {
        client.get(
            endpoint: "banners",
            contentId: "home") { result in
            switch result {
            case .success(let object):
                if let object = object as? [String: Any] {
                    self.banner = Banner(dict: object)
                } else {
                    print("Failed to parse response")
                }
            case .failure(let error):
                print("[ERROR]: \(error)")
            }
        }
    }
}

struct BannerView_Previews: PreviewProvider {
    static var previews: some View {
        BannerView()
    }
}

import MicrocmsSDK でSDKを使えるようにして、initで microCMS SDK を初期化します。

  • serviceDomain に https://xxxxx.microcms.io/ の xxxxx にあたる部分をセット
  • apiKey はダッシュボードからできる X-API-KEY の値をセット


画面表示時に呼ばれる fetchBanners() でコンテンツID home を指定してバナー情報を取得しています。

次に、今追加した BannerView を ContentView から表示されるように変更しましょう。

import SwiftUI

@main
struct ContentView: View {
    var body: some View {
        NavigationView {
            BannerView()
        }
    }
}

アプリを起動し、取得したバナーのコンテンツIDが画面に表示されていれば成功です。


バナー画像を表示する

それではバナー画像を表示していきましょう。
コンテンツIDをテキスト表示していた部分を ImageView を使った実装に切り替えます。

struct BannerView: View {
    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)
                     }
            }

            Text("数行の実装でバナーを実現できます。\n管理画面からバナーの差し替えも簡単です。")
                .font(.body)
                .padding(.top, 24)

            Spacer()
        }
        // -------------- ここまで

            .padding(12)
            .navigationTitle("バナー")
            .navigationBarTitleDisplayMode(.inline)
            .onAppear {
                fetchBanner()
            }    
    }
}


ネットワークから取得した画像を表示する ImageView クラスを追加します。

import SwiftUI
import UIKit

struct ImageView: View {
    @ObservedObject var imageLoader: ImageLoader
    
    init(url: URL) {
        imageLoader = ImageLoader(url: url)
    }

    var body: some View {
        Image(uiImage: imageLoader.image)
            .resizable()
            .aspectRatio(contentMode: .fit)
    }
}


画像データを取得する ImageLoader を追加します。

import Foundation
import SwiftUI
import Combine

class ImageLoader: ObservableObject {
    @Published var image = UIImage()
    
    init(url: URL) {
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data else { return }
            DispatchQueue.main.async {
                self.image = UIImage(data: data)!
            }
        }
        task.resume()
    }
}


microCMSとは関係の薄い部分なので詳細は省きますが、ネットワークから読み込むと画面に表示されるように実装しています。

これでmicroCMSに入稿したバナー画像を表示できるようになりました。
アプリを実行すると以下のような画面になっているはずです。


バナーをタップすると遷移先として設定しているURLが開きます。
microCMSの入稿画面でバナーの画像や遷移先URLを変更し、アプリの状態が変わることを確認してみてください。

環境

本記事は以下のバージョンで確認しています。バージョンの差異によって若干機能が異なる可能性があります。

  • Xcode 12.5
  • Swift 5.4


おわりに

今回はiOSアプリにバナーを実装する方法について解説しました。microCMSで入稿バナーの管理をすることで、入稿側も実装側もシンプルにバナー機能を実装することができると思います。この記事がご参考になれば嬉しいです。


-----

microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitterメールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!

まずは、無料で試してみましょう。

APIベースの日本製ヘッドレスCMS「microCMS」を使えば、 ものの数分でAPIの作成ができます。

microCMSを無料で始める

microCMSについてお問い合わせ

初期費用無料・14日間の無料トライアル付き。ご不明な点はお気軽にお問い合わせください。

お問い合わせ

microCMS公式アカウント

microCMSは各公式アカウントで最新情報をお届けしています。
フォローよろしくお願いします。

  • X
  • Discord
  • github

ABOUT ME

ひまらつ
SwiftやPythonやスプラトゥーンを楽しんでます