Firebase removeAllObservers() 在切换视图时不断调用 -Swift2 iOS
Firebase removeAllObservers() keeps making calls when switching views -Swift2 iOS
我阅读了有关此问题的其他堆栈溢出问答,但它似乎是一个 tabBarController 问题,我还没有找到任何相关内容。
我有一个带有 3 个选项卡的 tabBarController。 tab1 是我成功将信息发送到 Firebase 的地方。在 tab2 中,我有 tableView 成功地从 tab1 读取数据。
在 tab2 中,我的听众在 viewWillAppear 中。我删除了 viewDidDisappear 中的侦听器(我也尝试过 viewWillDisappear),这里的某处就是发生问题的地方。
override func viewDidDisappear(animated: Bool) {
self.sneakersRef!.removeAllObservers()
//When I tried using a handle in viewWillAppear and then using the handle to remove the observer it didn't work here either
//sneakersRef!.removeObserverWithHandle(self.handle)
}
一旦我从 tab2 切换到任何其他选项卡,第二次我回到 tab2,table 数据加倍,然后如果我再次切换选项卡并返回它三倍等。我尝试在里面设置监听器viewDidLoad 可防止 table 数据在我切换选项卡时重复,但当我从 tab1 发送新信息时,信息永远不会在 tab2 中更新。
根据 Firebase 文档和我在 Whosebug/google 上阅读的几乎所有其他内容,应该在 viewWillAppear 中设置侦听器并在 viewDidDisappear 中删除。
关于如何防止我的数据在标签之间来回切换时重复的任何想法?
tab1
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class TabOneController: UIViewController{
var ref:FIRDatabaseReference!
@IBOutlet weak var sneakerNameTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.ref = FIRDatabase.database().reference()
}
@IBAction func sendButton(sender: UIButton) {
let dict = ["sneakerName":self.sneakerNameTextField.text!]
let usersRef = self.ref.child("users")
let sneakersRef = usersRef.child("sneakers").childByAutoID()
sneakersRef?.updateChildValues(dict, withCompletionBlock: {(error, user) in
if error != nil{
print("\n\(error?.localizedDescription)")
}
})
}
}
tab2
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class TabTwoController: UITableViewController{
@IBOutlet weak var tableView: UITableView!
var handle: Uint!//If you read the comments I tried using this but nahhh didn't help
var ref: FIRDatabaseReference!
var sneakersRef: FIRDatabaseReference?
var sneakerArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.ref = FIRDatabase.database().reference()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let usersRef = self.ref.child("users")
//Listener
self.sneakersRef = usersRef.child("sneakers")
//I tried using the handle
//---self.handle = self.sneakersRef!.observeEventType(.ChildAdded...
self.sneakersRef!.observeEventType(.ChildAdded, withBlock: {(snapshot) in
if let dict = snapshot.value as? [String:AnyObject]{
let sneakerName = dict["sneakerName"] as? String
self.sneakerArray.append(sneakerName)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
}), withCancelBlock: nil)
}
//I also tried viewWillDisappear
override func viewDidDisappear(animated: Bool) {
self.sneakersRef!.removeAllObservers()
//When I tried using the handle to remove the observer it didn't work either
//---sneakersRef!.removeObserverWithHandle(self.handle)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sneakerArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("sneakerCell", forIndexPath: indexPath)
cell.textLabel?.text = sneakerArray[indexPath.row]
return cell
}
}
tab3 什么都不做。我只是将它用作备用选项卡,以
来回切换
感谢您提出这个问题。
我过去也遇到过同样的问题。我已经解决了这个问题。
1) 定义包含观察者列表的数组。
var aryObserver = Array<Firebase>()
2) 添加观察者如下。
self.sneakersRef = usersRef.child("sneakers")
aryObserver.append( self.sneakersRef)
3) 删除观察者如下。
for fireBaseRef in self.aryObserver{
fireBaseRef.removeAllObservers()
}
self.aryObserver.removeAll() //Remove all object from array.
removeAllObservers
方法工作正常。您当前遇到的问题是由一个小细节遗漏引起的:您从未清除 sneakerArray
.
的内容
注意:事件回调中不需要 dispatch_async
。 Firebase SDK 在主队列上调用此函数。
官方接受的答案由@vzsg 发布。我只是为遇到此问题的下一个人详细说明。给他的答案投赞成票。
基本上发生的事情是当您使用 .childAdded
时,Firebase 循环并从节点 (in my case the node is "sneakersRef"
) 抓取每个子节点。 Firebase 抓取数据,将其添加到数组 (in my case self.sneakerArray
),然后返回获取下一组数据,将其添加到数组等。通过在下一个循环开始时清除数组, FB 完成后数组将为空。如果你切换场景,你将始终有一个空数组,ui 将显示的唯一数据是 FB 再次循环节点。
我也摆脱了 dispatch_async 调用,因为他说 FB 调用主队列中的函数。我只用了 self.tableView.reloadData()
附带说明一下,您应该订阅 firebase-community.slack.com。那是官方的 Firebase slack 频道,也是我发布这个问题的地方,vzsg 回答了它。
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//CLEAR THE ARRAY DATA HERE before you make your Firebase query
self.sneakerArray.removeAll()
let usersRef = self.ref.child("users")
//Listener
self.sneakersRef = usersRef.child("sneakers")
//I tried using the handle
//---self.handle = self.sneakersRef!.observeEventType(.ChildAdded...
self.sneakersRef!.observeEventType(.ChildAdded, withBlock: {(snapshot) in
if let dict = snapshot.value as? [String:AnyObject]{
let sneakerName = dict["sneakerName"] as? String
self.sneakerArray.append(sneakerName)
//I didn't have to use the dispatch_async here
self.tableView.reloadData()
}
}), withCancelBlock: nil)
}
我阅读了有关此问题的其他堆栈溢出问答,但它似乎是一个 tabBarController 问题,我还没有找到任何相关内容。
我有一个带有 3 个选项卡的 tabBarController。 tab1 是我成功将信息发送到 Firebase 的地方。在 tab2 中,我有 tableView 成功地从 tab1 读取数据。
在 tab2 中,我的听众在 viewWillAppear 中。我删除了 viewDidDisappear 中的侦听器(我也尝试过 viewWillDisappear),这里的某处就是发生问题的地方。
override func viewDidDisappear(animated: Bool) {
self.sneakersRef!.removeAllObservers()
//When I tried using a handle in viewWillAppear and then using the handle to remove the observer it didn't work here either
//sneakersRef!.removeObserverWithHandle(self.handle)
}
一旦我从 tab2 切换到任何其他选项卡,第二次我回到 tab2,table 数据加倍,然后如果我再次切换选项卡并返回它三倍等。我尝试在里面设置监听器viewDidLoad 可防止 table 数据在我切换选项卡时重复,但当我从 tab1 发送新信息时,信息永远不会在 tab2 中更新。
根据 Firebase 文档和我在 Whosebug/google 上阅读的几乎所有其他内容,应该在 viewWillAppear 中设置侦听器并在 viewDidDisappear 中删除。
关于如何防止我的数据在标签之间来回切换时重复的任何想法?
tab1
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class TabOneController: UIViewController{
var ref:FIRDatabaseReference!
@IBOutlet weak var sneakerNameTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.ref = FIRDatabase.database().reference()
}
@IBAction func sendButton(sender: UIButton) {
let dict = ["sneakerName":self.sneakerNameTextField.text!]
let usersRef = self.ref.child("users")
let sneakersRef = usersRef.child("sneakers").childByAutoID()
sneakersRef?.updateChildValues(dict, withCompletionBlock: {(error, user) in
if error != nil{
print("\n\(error?.localizedDescription)")
}
})
}
}
tab2
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class TabTwoController: UITableViewController{
@IBOutlet weak var tableView: UITableView!
var handle: Uint!//If you read the comments I tried using this but nahhh didn't help
var ref: FIRDatabaseReference!
var sneakersRef: FIRDatabaseReference?
var sneakerArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.ref = FIRDatabase.database().reference()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let usersRef = self.ref.child("users")
//Listener
self.sneakersRef = usersRef.child("sneakers")
//I tried using the handle
//---self.handle = self.sneakersRef!.observeEventType(.ChildAdded...
self.sneakersRef!.observeEventType(.ChildAdded, withBlock: {(snapshot) in
if let dict = snapshot.value as? [String:AnyObject]{
let sneakerName = dict["sneakerName"] as? String
self.sneakerArray.append(sneakerName)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
}), withCancelBlock: nil)
}
//I also tried viewWillDisappear
override func viewDidDisappear(animated: Bool) {
self.sneakersRef!.removeAllObservers()
//When I tried using the handle to remove the observer it didn't work either
//---sneakersRef!.removeObserverWithHandle(self.handle)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sneakerArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("sneakerCell", forIndexPath: indexPath)
cell.textLabel?.text = sneakerArray[indexPath.row]
return cell
}
}
tab3 什么都不做。我只是将它用作备用选项卡,以
来回切换感谢您提出这个问题。
我过去也遇到过同样的问题。我已经解决了这个问题。
1) 定义包含观察者列表的数组。
var aryObserver = Array<Firebase>()
2) 添加观察者如下。
self.sneakersRef = usersRef.child("sneakers")
aryObserver.append( self.sneakersRef)
3) 删除观察者如下。
for fireBaseRef in self.aryObserver{
fireBaseRef.removeAllObservers()
}
self.aryObserver.removeAll() //Remove all object from array.
removeAllObservers
方法工作正常。您当前遇到的问题是由一个小细节遗漏引起的:您从未清除 sneakerArray
.
注意:事件回调中不需要 dispatch_async
。 Firebase SDK 在主队列上调用此函数。
官方接受的答案由@vzsg 发布。我只是为遇到此问题的下一个人详细说明。给他的答案投赞成票。
基本上发生的事情是当您使用 .childAdded
时,Firebase 循环并从节点 (in my case the node is "sneakersRef"
) 抓取每个子节点。 Firebase 抓取数据,将其添加到数组 (in my case self.sneakerArray
),然后返回获取下一组数据,将其添加到数组等。通过在下一个循环开始时清除数组, FB 完成后数组将为空。如果你切换场景,你将始终有一个空数组,ui 将显示的唯一数据是 FB 再次循环节点。
我也摆脱了 dispatch_async 调用,因为他说 FB 调用主队列中的函数。我只用了 self.tableView.reloadData()
附带说明一下,您应该订阅 firebase-community.slack.com。那是官方的 Firebase slack 频道,也是我发布这个问题的地方,vzsg 回答了它。
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//CLEAR THE ARRAY DATA HERE before you make your Firebase query
self.sneakerArray.removeAll()
let usersRef = self.ref.child("users")
//Listener
self.sneakersRef = usersRef.child("sneakers")
//I tried using the handle
//---self.handle = self.sneakersRef!.observeEventType(.ChildAdded...
self.sneakersRef!.observeEventType(.ChildAdded, withBlock: {(snapshot) in
if let dict = snapshot.value as? [String:AnyObject]{
let sneakerName = dict["sneakerName"] as? String
self.sneakerArray.append(sneakerName)
//I didn't have to use the dispatch_async here
self.tableView.reloadData()
}
}), withCancelBlock: nil)
}