post Image
[swift] Firebase Realtime Databaseのリスナーについて

firebaseに触れる機会があったので、こちら参加してみました
主にリスナーについてさらっと軽め書いていこうかと

Firebase Realtime Database とは

Firebase Realtime Database はクラウドにホストされたデータベースです。データは JSON として保存され、接続されているすべてのクライアントとリアルタイムに同期されます。Android、iOS、JavaScript SDK を使用してクロスプラットフォーム アプリを構築すると、すべてのクライアントによって 1 つの Realtime Database インスタンスが共有され、最新のデータによる更新が自動的に受信されます。

日本語の公式ドキュメントより

イベントリスナーのアタッチ

リスナーはデータの初期状態で1回トリガーされます。またデータが変更されると、そのたびに再びトリガーされます
observeSingleEventOfTypeメソッドを使用すると、1度だけトリガーされるイベントを設定できます

let userID = FIRAuth.auth()?.currentUser?.uid
ref.child("users").child(userID!).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
  // Get user value
  let username = snapshot.value!["username"] as! String
  let user = User.init(username: username)

  // ...
  }) { (error) in
    print(error.localizedDescription)
}

イベントリスナーの種類

イベントの種類は全部で5種類あります

イベントの種類 呼ばれるタイミング
FIRDataEventTypeValue パス全体に対する全ての変更に対して呼ばれる
FIRDataEventTypeChildAdded データが追加されたとき、リスナーをセットしたときに呼ばれる。データが無いときは呼ばれない
FIRDataEventTypeChildRemoved データが削除されたとき
FIRDataEventTypeChildChanged データが変更されたとき。.added, .removedと併用して使用する
FIRDataEventTypeChildMoved データの並び替えが発生したとき

実際にイベントリスナーをつけてみよう

はじめに

タイタンというロボットが召喚された回数(=fallCount)がカウントアップされたとき、labelの回数表示も更新するという感じで.valueイベントで監視していきます

データ構造

"titan": {
    "fallCount": { 
        0
    }
}

FIRDatabaseReference、FIRDatabaseHandleをまとめて定義しておくといいと思います

Database.swift
typealias ObserverReturnValue = (ref: FIRDatabaseReference, handle: FIRDatabaseHandle)

実際にリスナーをセット

ViewController.swift
@IBOutlet weak var fallCountLabel: UILabel!

var observer: Database.ObserveReturnValue
observer = Observe.observeFallCount(completion { count in
    if let count = count {
        fallCountLabel.text = count
    }
})
Observe.swift
static func observeFallCount(completion: @escaping ((Int?) -> ())) -> Database.ObserverReturnValue {
    let path = "taitan/fallCount" 
    let ref = FIRDatabase.database().reference().child(path)
    let handle = ref.observe(.value, with: { snapshot in
        if snapshot.exists(), let count = snapshot.value {
            completion?(count)
        } else {
            completion?(nil)
        }
    })
    return (ref: ref, handle: handle)
}

不要になったリスナーはremoveしてあげましょう

ViewController.swift
func removeObserve() {
    if let ref = , observer.ref, let handle = observer.handle {
        ref.removeObserver(withHandle: handle)
    }
}

おわり

これからたまーにアウトプットしていこうと思ってます。なにか間違いなどありましたら教えていただけると幸いです。おつかれさまでした


『 Swift 』Article List