はじめに
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コレクションにはfirst、last、bornの三つのデータを追加していたのでそれをクラスで定義します。
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)
}
}
以上。