Help us understand the problem. What is going on with this article?

【Swift】Codableを用いてCloud FirestoreのドキュメントをEncode&Decodeする実装

はじめに

Webサーバなどを経由せずに、クライアントサイドから直接データを登録できるのがFirestoreの強みですが、データを保存するには下記のコードのようにkey:value形式のデータを作成する必要があります。(公式ドキュメント参照)

// usersコレクションにデータを追加する
var ref: DocumentReference? = nil
ref = db.collection("users").addDocument(data: [
    "first": "Ada",
    "last": "Lovelace",
    "born": 1815
]) { err in
    if let err = err {
        print("Error adding document: \(err)")
    } else {
        print("Document added with ID: \(ref!.documentID)")
    }
}

しかし、いかんせん値の指定がkey:value形式なので、key名をハードコーディングする必要があります。
せっかくSwiftを使っているならデータをEncode&DecodeしてClassやStructで扱いたいですよね?
今回はCodableを用いてFirestoreのドキュメントのデータをEncode&Decodeする実装を書きたいと思います。

環境構築

まずは公式ドキュメントを参考に、Firebaseのプロジェクトを作成しましょう。
そのあとはまたまたこちらの公式ドキュメントを参考にCloud Firestore データベースを作成しましょう。
ドキュメントのCloud Firestore を初期化するまで進めたら環境構築は十分です。Podfileは下記のようになっています。

pod 'Firebase/Core'
pod 'Firebase/Firestore'

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

実装

Encode処理

冒頭のusersコレクションにドキュメントを追加する処理を、Encodeしたデータを使った実装に置き換えてみます。
usersコレクションにはfirstlastbornの三つのデータを追加していたのでそれをクラスで定義します。

User.swift
class User: Codable {
    internal let first: String
    internal let last: String
    internal let born: Int

    init(first: String, last: String, born: Int) {
        self.first = first
        self.last = last
        self.born = born
    }
}

定義したUserクラスをEncodeして、そのデータをusersコレクションに追加します。

import Firebase

// UserのEntity作成
let user: User = User(first: "Ada", last: "Lovelace", born: 1815)
var encodedUserData: [String: Any]!
do {
    // エンコード処理
    encodedUserData = try Firestore.Encoder().encode(user)
}
catch let e {
    fatalError(e.localizedDescription)
}
// usersコレクションにエンコードしたデータを追加する
var ref: DocumentReference? = nil
ref = Firestore.firestore().collection("users").addDocument(data: encodedUserData) { err in
    if let err = err {
        print("Error adding document: \(err)")
    } else {
        print("Document added with ID: \(ref!.documentID)")
    }
}

これでkey名をハードコーディングする必要がなく、追加したいデータをクラスで管理することができました。

Decode

上記でEncodeしたデータをusersコレクションに追加できたので、それらのデータ一覧を取得してDecodeする処理を実装したいと思います。

// usersコレクションから、userのデータのドキュメントの一覧を取得する
Firestore.firestore().collection("users").getDocuments { (snapshot, error) in
    if let error: Error = error {
        print(error.localizedDescription)
        return
    }
    guard let snapshot: QuerySnapshot = snapshot else {
        return
    }
    var users: [User] = []
    do {
        for document in snapshot.documents {
            // key:value形式のデータをDecodeする
            let user: User = try Firestore.Decoder().decode(User.self, from: document.data())
            users.append(user)
        }
        // usersの一覧取得成功!!
    }
    catch let e {
        fatalError(e.localizedDescription)
    }
}

以上。

tsuruken
フリーランスとして活動しています。 iOSメインです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした