デフォルトのモーダルをそのまま配信するとiOSのデザインぽくないのでカスタマイズを施すようにしてみる。
Firebase In-App Messagingのセットアップ自体は↓を参考にしてください。
[Swift/Firebase] Firebase In-App Messaging を使ってみる実装
(@mainのview.swift)
全パターン実装は時間かかるので、今回はモーダルタイプの配信を受け取って表示させるようにします。
import SwiftUI
import FirebaseInAppMessaging
@main
struct SwiftUI_PlaygroundApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
HomeView()
.modalInAppMessage { modalMessage, delegate in
InAppMessagingModalView(modalMessage: modalMessage, delegate: delegate)
}
// .imageOnlyInAppMessage { imageOnlyMessage, delegate in
// ImageOnlyInAppMessageView(imageOnlyMessage: imageOnlyMessage, delegate: delegate)
// }
// .cardInAppMessage { cardInAppMessage, delegate in
// CardInAppMessageView(cardInAppMessage: cardInAppMessage, delegate: delegate)
// }
// .bannerInAppMessage { bannerInAppMessage, delegate in
// BannerInAppMessageView(bannerInAppMessage: bannerInAppMessage, delegate: delegate)
// }
}
}
}
modalMessage
にFirebaseコンソールで指定した値 (URL, Text, Boyd,,,etc)が諸々渡ってくるのでそれをViewで受け取るようにしています、delegateも同様。
InAppMessagingModalView
実際にモーダルとして表示するためのView, バツボタンの画像データは各々好きなものに変えてください。
import SwiftUI
import FirebaseInAppMessaging
struct InAppMessagingModalView: View {
// MARK: - Properties
let modalMessage: InAppMessagingModalDisplay
let delegate: InAppMessagingDisplayDelegate
// MARK: - Body
var body: some View {
VStack(spacing: 4) {
pullCloseButton
inAppMessagingModalView
}
.padding(.horizontal, 20)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.background(
Color.black
.opacity(0.5)
.ignoresSafeArea()
.onTapGesture {
delegate.messageDismissed?(modalMessage, dismissType: .typeUserTapClose)
}
)
}
// 右上閉じるボタン
var pullCloseButton: some View {
HStack {
Button {
delegate.messageDismissed?(modalMessage, dismissType: .typeUserTapClose)
} label: {
Image("img_headback")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
.frame(width: 40, height: 40)
.padding(2)
}
.frame(maxWidth: .infinity, alignment: .trailing)
}
// モーダル内容
var inAppMessagingModalView: some View {
VStack(spacing: 20) {
inAppTitleText
inAppImage
inAppBodyText
inAppButton
}
.padding(24)
.background(.white)
.frame(maxWidth: .infinity)
.cornerRadius(12)
}
// メイン画像
var inAppImage: some View {
let imageURL = modalMessage.imageData?.imageURL
return AsyncImage(url: URL(string: imageURL ?? "")) { image in
image.resizable()
.aspectRatio(contentMode: .fit)
} placeholder: {
ProgressView()
}
}
// タイトル
var inAppTitleText: some View {
Text(modalMessage.title)
.font(.system(size: 16, weight: .bold))
.foregroundColor(.black)
}
// 内容
var inAppBodyText: some View {
Text(modalMessage.bodyText ?? "")
.font(.system(size: 14))
.foregroundColor(.gray)
.multilineTextAlignment(.center)
}
// 下部ボタン
var inAppButton: some View {
Button(action: {
guard let url = modalMessage.actionURL else { return }
UIApplication.shared.open(url)
delegate.messageDismissed?(modalMessage, dismissType: .typeUserTapClose)
}, label: {
Text(modalMessage.actionButton?.buttonText ?? "")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.black)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.overlay(
RoundedRectangle(cornerRadius: 80)
.stroke(.black, lineWidth: 3)
)
.background(.white)
.frame(height: 48)
.padding(.horizontal, 6)
}
}
検証
序盤に貼った関連記事内にもありますが、In-Appの本番配信だと1日1回?くらいしか検証できないので検証用にIDを取得してそちらを使って表示の検証をするようにします。
AppDelegateとか最初に表示されるViewとかに以下を入れる。
Installations.installations().installationID { id, error in
if let error = error {
print("Error retrieving installation ID: \(error.localizedDescription)")
} else if let id = id {
print("Firebase Installation ID: \(id)")
}
}
これでIDを確認できるようになるので、↑の関連記事のフローを参考にテスト配信して表示されるか確認してください。