概要
Firebase からデータを取得する場合 observe or observeSingleEvent を使うと思います
observeSingleEvent の場合は特に問題ないのですがリアルタイムでデータを取得したい場合には observe を使います
その場合に何故か 1 度しかデータを更新していないのに observe が複数回コールされる現象に遭遇したので対策を紹介します
環境
- macOS 10.13.2
- Xcode 9.2 (9C40b)
- Firebase 4.8.2
確認する点
いくつか紹介します
単純にデータを複数回更新していないか
Swift からデータを更新する際には setValue
or updateChildValues
を使うと思います
単純にこれらが複数回コールされていないか確認しましょう
例えば touchDown などのイベントが発生したら上記メソッドを呼ぶようなケースだとすると連打などの対策をしていないと同じデータが複数回更新される可能性があります
Firebase の場合データが同じであっても更新イベントがあれば observe してしまいます
observe を removeObserver していない
自分はこっちでハマリました
observe の場合 removeObserver をしないといくら View が変わってもデータの監視が続いてしまうようです
これは SpriteKit でも同様で SKScene が変わった時に removeObserver していないと複数回コールされてしまうことがあります
removeObserver は例えば以下のように使います
var bmref = DatabaseReference()
var handler: UInt = 0
bmref = rootRef.child("path/to/data")
handler = bmref.observe(.value, with: { (snapshot) in
bmref.removeObserver(withHandle: handler)
move(to: scene)
})
move(to :scene)
は適当にこちらで定義したシーンを移動するためのメソッドです
要するにシーンの移動直前に removeObserver
を呼ぶようにしましょう
removeObserver
の引数には observe を識別するためのハンドラが必要です
これは observe を登録した際の戻り値として取得することができます
ハンドラはインスタンス変数などにして別のメソッドからも参照できるようにしておきましょう
これで observe を削除することができます
observe が複数コールされる場合の影響
自分の場合は SpriteKit 上で使っていたのですが observe が複数回コールされることで fps が低下するという現象が発生しました
具体的に言うと SKAction.move などで動いているノードがある状態で observe が複数回コールされるとノードが一瞬 (0.5 - 1 秒ほど) 停止する状態になります
これが必要最低限のみコールされるようになることで fps が落ちることなくノードが動き続けてくれます
最後に
Swift + Firebase で observe が複数回コールされてしまう場合の対策を紹介しました
observe が削除されていない場合には削除するように修正してみてください
それでも重い、fps が落ちるという場合には単純に Firebase に対してアクセスしすぎていないか確認してみてください (1 秒間に 100 回データを更新するような処理をしていないかなど)
そういう場合にはずっと observe しないで定期的に observeSingleEvent するような仕組みに変更するようにしてみてください
0 件のコメント:
コメントを投稿