ドキュメントによると、オブザーバーが不要になった場合は、observeEventType:withBlock
を呼び出してオブザーバーを削除する必要があります。
ViewDidDisAppear
内で呼び出されるサンプルを見てきました。また、このメソッドと呼ばれるいくつかのObj-Cコードがdeinit
内にありますが、これはSwiftでは必要ありません。
ただし、私の単純なアプリでは、アプリ内にいる限りデータを同期したいと思っています。この場合、observeEventType:withBlock
に電話する必要がありますか?
Firebase WebサイトでChat-Swiftサンプルコードを確認しましたが、observeEventType:withBlock
が見つかりませんでした。
observeEventType:withBlock
:を呼び出さなくても大丈夫という意味ですか。アプリの使用中にオブザーバーをオンにしたい場合はどうすればよいですか?
ありがとうございました。
[〜#〜] update [〜#〜]
ジェイとデビッドに感謝します。 ViewWillAppearで観察し、ViewDidDisappearで削除するのは理にかなっていると思います。
ただし、observeEventTypeを使用してノードへの値の変更を監視しており、UIがある場合は更新します。 ViewWillAppearに入れたら:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
ref.observeEventType(.Value, withBlock: { snap in {
// **update UI if there is any Value change**
})
}
viewWillAppear
に配置する場合の問題は、値の変更の有無に関係なく、ビューが表示されるたびに呼び出されることです。このため、スナップショットがダウンロードされ、ビューに戻るたびにUIが更新されます。これは逆効果になります。
ChildAdded
/ChildRemoved
も試しましたが、参照からのパスではなく、最後のノードのみが返されます。
たとえば、ref/child1/child2/child3/valueに追加すると、ChildAdded
はchild3/valueのみを返します。
したがって、Valueを監視する必要がある場合は、ViewDidLoad
に入れる方が良いように思われますか?このように、ビューがロードされたときにスナップショットを1回取得し、変更があるたびに繰り返しますが、ビューが表示されたという理由だけでスナップショットを取得することはありません。
@Jayの優れた答えに基づいて構築するには:
UIViewController
で、プロパティとして参照を作成します。 viewDidLoad
で参照を初期化します。 viewWillAppear
のイベントを観察します。 viewDidDisappear
のオブザーバーを削除します。
class MyViewController: UIViewController {
var ref: Firebase!
// Called only on load, great place to initialize
override func viewDidLoad() {
super.viewDidLoad()
ref = Firebase(url: "https://<YOUR-FIREBASE-APP>.firebaseio.com/updates")
}
// Can be called many times to go on screen
// Syncing should only occur when on view to conserve memory
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
ref.observeEventType(.Value, withBlock: { snap in {
// do something with the data
})
}
// Can be called many times to off screen
// Remove observers on the ref to conserve memory
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
ref.removeAllObservers()
}
}
編集ごと:
The problem with putting it in viewWillAppear is that, it gets called every time the view appears, regardless of Value change or not. Because of this, the snapshot is downloaded and my UI gets refreshed every time I return to the view. This becomes counterproductive.
Firebaseはスピードを重視して構築されています。これらは、これらの状況を処理するいくつかの機能を備えているため、クライアントに任せるようなものです。
Firebaseクライアントにはキャッシュが組み込まれています。 viewDidAppear
でメガバイトのデータをダウンロードしない限り、更新はわずかです。オブザーバーがviewDidAppear
を起動しても、必ずしもデータを再度ダウンロードしているとは限りません。 viewDidAppear
関数は、オブザーバーが属する場所です。
参考までに、私はiOSで作業するFirebaseの従業員です。
observeEventType:withBlockは、ノードを監視するために使用されるものです。
アプリがノードを監視していると、アプリを終了するか、Firebaseに監視を停止するように指示しない限り、アプリは引き続き監視します。
監視を停止するには、次のように監視を開始したときに返されたハンドルを使用できます。
//start observing and get a handle
FirebaseHandle handle = [ref observeEventType:FEventTypeValue withBlock:^(FDatasnapshot* snapshot) {
// do some stuff with the snapshot data
}];
[ref removeObserverWithHandle:handle]; //stop observing using the handle
またはこのように
[ref removeAllObservers];
ViewWillAppear()およびviewWillDisappear()での監視と監視の停止は機能しますが、View Controllerが表示されたときに、追加された子値(.added/.valueを監視タイプに使用する場合)が再度発生します。
私はviewDidLoad()で観測を設定し、deinitで観測を停止することを好みます。
オブザベーションを設定した後にdeinitが呼び出されないと言う人もいますが、その理由は、オブザベーションを設定すると、オブザーバーのクロージャが自己を強く保持しているため、deinitが呼び出されないためです。クロージャー内に弱いまたは所有されていないものを設定できます。
これが例です。
class SomeViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
someRef.observe(.childAdded) { [weak self] (snapshot) in
guard let weakSelf = self else { return }
...
}
}
deinit {
print("deinit called")
someRef.removeAllObservers()
}
}
[weak self]と書くことを忘れないでください。そうしないと、deinitが呼び出されることはありません。それが役に立てば幸い。