LoginSignup
1
3

More than 3 years have passed since last update.

【Swift】iOSアプリでFirestoreからデータを取得する方法

Posted at

昔、AWSを使って個人アプリを開発していたのですが、APIを作ってEC2に配置して、RDS設定して・・・
とにかく色々大変だったので、もっと簡単にCRUD機能を実現したいなと思いました

今更かもしれませんが、FirestoreでAPIを作らずに簡単にCRUD機能を実現できることを知ったので、今回はデータを取得するところまでをやってみたいと思います

ソースコードはこちらから↓

環境

Xcode12.4
Swift5

Firebaseと連携する

下記の公式ドキュメントに沿って、iOSアプリとFirebsseの連携をしてみる

新規プロジェクト作成

Firebaseコンソール画面から新規にプロジェクトを追加する

プロジェクト追加

任意のプロジェクト名を記載して続行

今回はGoogleアナリティクスへの連携はOFFにして、プロジェクトを作成
ONにすると、次の画面で連携するGoogleアカウントを指定する必要があります

新規にプロジェクトが作成されました

Firestoreでデータベース作成

早速、FireStoreでデータを作成していきます

コンソール画面からFirestore Databaseを選択してデータベースを作成

テストモードを選択して次に行きます

公式ドキュメントによると、本番環境モード(ドキュメントではロックモード)では、モバイルアプリから直接Firestoreのデータを参照できないため、APIやBatchを経由する必要があるみたいです。
そのため、今回はモバイルアプリから直接データを参照できるテストモードを選択します

ロックモード
モバイルおよびウェブ クライアントからのすべての読み書きを拒否します。認証されたアプリケーション サーバー(C#、Go、Java、Node.js、PHP、Python、Ruby)は引き続きデータベースにアクセスできます。
https://firebase.google.com/docs/firestore/quickstart?hl=ja#create

ロケーションをは利用場所から一番近いasia-northeast1(東京)を選択します

日本にはロケーションが東京と大阪にあるみたいです
ロケーションは一度しか設定できないため要注意です

asia-northeast1 東京
asia-northeast2 大阪
https://firebase.google.com/docs/firestore/locations?hl=ja#types

データ追加

今回はコンソール画面からPersonデータを2件追加しました

Firestoreだと配列の中に配列を入れることができないため、今回はhobbies配列の中にmapタイプでnameやyearのデータを入れました。referenceタイプを指定すると、別のドキュメントを指定することも可能です。

ちなみに、コレクションやドキュメントの説明については、以下の記事がとてもわかりやすかったです

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

Firestoreのライブラリを入れていきます。今回はCocoaPodsを利用します。
Podsの初期化については以下の記事が参考になると思います。

指定のライブラリをPodfileに追加します
※Swiftを利用する場合は、FirebaseFirestoreSwiftも追加するらしい。

pod 'Firebase/Firestore'
# Optionally, include the Swift extensions if you're using Swift.
pod 'FirebaseFirestoreSwift'

インストールします

pod install

Firebseの初期化

Firestoreを利用する際に初期化が必要となるため、Appdelegateで初期化しておきます

import UIKit
import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Firebase初期化
        FirebaseApp.configure()
        return true
    }
}

ビルドしたらコンパイルエラーになりました・・・

Terminating app due to uncaught exception 'com.firebase.core', reason: '`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find a valid GoogleService-Info.plist in your project. Please download one from https://console.firebase.google.com/.'

そもそもFirebaseにiOSプロジェクトを追加していなかったです
初期設定の際にGoogleService-Info.plistを追加するのですが、今回はそのファイルがなくてエラーとなっています

FirebaseにiOSプロジェクト追加

少し話が前後してしまい申し訳ないですが、FirebaseにiOSプロジェクトを追加します

コンソール画面でiOSを選択

BundleIDとニックネームを記載

GoogleService-Info.plistをダウンロード
後続は前述したようにpodでインストールとFirebaseの初期化処理なので、割愛します

GoogleService-Info.plistをプロジェクトのRoot配下に追加

無事にビルドできました(失礼しました!)

Firestoreからデータ取得

Firestoreで追加したデータを構造体(Person,Hobby)に格納しました
データは非同期で取得されます

ViewController.swift
import UIKit
import Firebase

struct Person {
    var name: String
    var age: Int
    var hobbys: [Hobby]
}

struct Hobby {
    var name: String
    var year: Int
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // リスト初期化
        var persons: [Person] = []

        // FirestoreのDB取得
        let db = Firestore.firestore()
        // personsコレクションを取得
        db.collection("persons").getDocuments() { collection, err in
            // エラー発生時
            if let err = err {
                print("Error getting documents: \(err)")
            } else {
                // コレクション内のドキュメントを取得
                for document in collection!.documents {
                    // hobbiesフィールドを取得
                    guard let hobbyDicList: [[String : Any]] = document.get("hobbies") as? [[String : Any]] else {
                        continue
                    }

                    // リスト初期化
                    var hobbies: [Hobby] = []

                    // hobbies内のフィールドを取得
                    for hobbyDic in hobbyDicList {
                        guard let hobbyName = hobbyDic["name"] as? String ,
                              let hobbyYear = hobbyDic["year"] as? Int else {
                            continue
                        }
                        // Hobbyを作成
                        let hobby = Hobby(name: hobbyName, year: hobbyYear)
                        // リストに追加
                        hobbies.append(hobby)
                    }

                    // Personフィールドを取得
                    guard let personName = document.get("name") as? String,
                          let personAge = document.get("age") as? Int else {
                        continue
                    }

                    // Personを作成
                    let person = Person(name: personName, age: personAge, hobbys: hobbies)

                    // リストに追加
                    persons.append(person)
                }
            }
            // コンソール出力
            print(persons)
        }
    }
}

出力結果より、Firestoreに追加したデータを無事に取得することができました!

[firestore_sample_app.Person(name: "jiro", age: 35, hobbys: [firestore_sample_app.Hobby(name: "climbing", year: 10)]), firestore_sample_app.Person(name: "taro", age: 20, hobbys: [firestore_sample_app.Hobby(name: "baseball", year: 5), firestore_sample_app.Hobby(name: "tennis", year: 8)])]

おわりに

今回、Firestoreを利用してみましたが、とても使いやすかったです
シンプルな機能ならFirebaseだけで事足りそうだなと感じました

ユーザー認証、ストレージ機能など他にも様々な機能が用意されているので、色々試してみたいと思います
(サーバ側はFirebaseに任せてiOSアプリに注力できそうです)

最後まで読んで頂きありがとうございます!

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3