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

FirebaseのRealtimeDatabaseから新規追加されたデータを逐次取得する

FirebaseのRealtimeDatabaseから新規追加されたデータを逐次取得する

はじめに

Firebaseのリアルタイムデータベースを使い、位置情報をリアルタイムで共有するアプリを作りたいと思い作った時に逐次最新のデータを取得する方法がわからずハマったのでここに残します。

データベースの構造

今回は、このような構造にしました。

一覧表示用
スクリーンショット 2019-06-21 1.30.13.png

データ格納用
スクリーンショット 2019-06-20 19.42.33.png

データ格納

インデックス用のデータ格納

インデックスとしては、日付とUUID(ユニークなID)を格納します。

writeUUID = UUID().uuidString
if let writeUUID = writeUUID {
    let value: [String:Any] = [
        keyDate:Date().timeIntervalSince1970,
        keyUUID:writeUUID
    ]
    fireDatabase.child("index").childByAutoId().setValue(value)
}

位置データの格納

緯度と経度をインデックス用のUUIDと一緒に格納します。

let value: [String:Any] = [
    keyDate:Date().timeIntervalSince1970,
    keyLatitude:latitude,
    keyLongitude:longitude
]
fireDatabase.child("data").child(writeUUID).child("location").childByAutoId().setValue(value)

データの取得

インデックス用のデータ取得

ここでは、一覧として既存の格納されているインデックス用のデータを一括で取得します。

fireDatabase.child("index").observeSingleEvent(of: .value, with: { (snapshot) in
    // Get user value
    guard let values = snapshot.value as? [String:Any] else { return }
    values.forEach({ (key,value) in
        guard let record = value as? [String:Any] else { return }
        guard let timeInterval1970 = record[self.keyDate] as? TimeInterval else { return }
        let date = Date(timeIntervalSince1970: timeInterval1970)
        guard let uuid = record[self.keyUUID] as? String else { return }
        // ここに何か処理を書く
    })
}) { (error) in
    print(error.localizedDescription)
}

位置データの取得

位置データはリアルタイムで格納されると1件づつ取得できます。
ここでは、queryOrdered(byChild: "date")を使い日付で並び替えています。

fireDatabase.child(keyData).child(writeUUID).child("location").queryOrdered(byChild: "date").observe(.childAdded) { (snapshot) in
    guard let record = snapshot.value as? [String:Any] else { return }
    guard let latitude = record[self.keyLatitude] as? CLLocationDegrees else { return }
    guard let longitude = record[self.keyLongitude] as? CLLocationDegrees else { return }
    guard let timeInterval1970 = record[self.keyDate] as? TimeInterval else { return }
    let date = Date(timeIntervalSince1970: timeInterval1970)
    print("date:\(date) latitude:\(latitude) , longitude:\(longitude)")
    // ここに何か処理を書く
}

最後に

いかがでしたでしょうか?意外と簡単にリアルタイムデータベースを活用できました。
日付順に並び替えするポイントさえ掴めば意外と簡単に実装できます。

Why do not you register as a user and use Qiita more conveniently?
  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
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