はじめに
アプリ開発を行なっていく中で、FirebaseのFirestoreを使用してデータ保存ができるようにする方法を学んだので、備忘録として内容をまとめます。
この記事では、タイトルと内容を入力して「メモを追加」をタップすると、内容がリストに追加されてFirestoreに保存されるサンプルアプリを元に解説します。
環境
【Xcode】16.2
【iOS】18.2
【macOS】Sequoia 15.3.1
【Firebase iOS SDK】 11.11.0
1. Firebaseプロジェクトを作成する
- Firebase Console にアクセス
- 「プロジェクトを作成」をクリック
- プロジェクト名を入力、Google AnalyticsはオフでもOK
- 「アプリを追加」でiOSアプリを選択
- Bundle IDを入力 (Xcodeの
Signing & Capabilities
で確認) -
GoogleService-Info.plist
をダウンロード、Xcodeプロジェクトに追加
2. Firebase SDK をXcodeに導入する
-
Xcodeメニューから「File > Add Package Dependencies...」を選択
-
パッケージURLに以下を入力
https://github.com/firebase/firebase-ios-sdk
-
バージョンは「Up to Next Major」でOK
-
必要なライブラリを追加(今回は下記の2つ)
- FirebaseCore
- FirebaseFirestore
3. Firebaseをアプリ起動時に初期化する
- App構造体(App.swift)に下記を追加して、アプリ起動時にFirebaseを初期化するようにする
import SwiftUI
import Firebase
@main
struct FirebaseTestApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
FirebasePracticeView()
}
}
}
4. Firestore用のデータモデルを作成する
- Firestoreと連携するため、Codableプロトコルを採用
- idには一意なUUIDを設定
import SwiftUI
struct Memo: Identifiable, Codable {
var id: String = UUID().uuidString
var title: String
var content: String
}
5. Firestoreにデータを保存するViewModelを作成する
- 保存時にはドキュメントIDをメモのIDと合わせる。
import Foundation
import FirebaseFirestore
class MemoViewModel: ObservableObject {
@Published var memos: [Memo] = []
private let db = Firestore.firestore()
private let collectionName = "memos"
// Firestoreから読み込む
func fetchMemos() {
db.collection(collectionName).getDocuments { snapshot, error in
if let error = error {
print("読み込みエラー: \(error)")
return
}
self.memos = snapshot?.documents.compactMap { doc in
try? doc.data(as: Memo.self)
} ?? []
}
}
// Firestoreに保存する
func addMemo(_ memo: Memo) {
do {
_ = try db.collection(collectionName).document(memo.id).setData(from: memo)
} catch {
print("保存エラー: \(error)")
}
}
}
6. Viewを作成
- onAppearでアプリ起動時にFirestoreからメモ一覧を取得。
- メモを追加したら即座にリストを更新するため、fetchMemos()を再度呼び出す。
import SwiftUI
struct FirebasePracticeView: View {
@StateObject private var viewModel = MemoViewModel()
@State private var title: String = ""
@State private var content: String = ""
var body: some View {
NavigationView {
VStack {
TextField("タイトル", text: $title)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("内容", text: $content)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("メモを追加") {
let newMemo = Memo(title: title, content: content)
viewModel.addMemo(newMemo)
title = ""
content = ""
viewModel.fetchMemos()
}
.padding()
List(viewModel.memos) { memo in
VStack(alignment: .leading) {
Text(memo.title).bold()
Text(memo.content)
}
}
}
.padding()
.navigationTitle("メモ一覧")
.onAppear {
viewModel.fetchMemos()
}
}
}
}
まとめ
- GoogleService-Info.plistをXcodeプロジェクトに追加する
- FirebaseApp.configure()をアプリ起動時に実行する
- FirestoreとSwiftのデータモデルはCodableを使って連携
- ViewModelでFirestoreとのデータやりとりを担当し、Viewはデータバインディング