如何在不打印两次数据的情况下重新加载 UITableView?
How to reload UITableView without printing data twice?
我有一个用作 UITableView 的 SlackTextViewController 视图。我正在使用 public 字符串在 "states" 之间切换,允许它读取特定状态下的一组数据和另一状态下的另一组数据。问题是当我来回切换到原始状态时,它打印数据 2、3、4 次;和我来回一样多。我正在从 Firebase 服务器加载数据,我认为这可能是 Firebase 问题。这是我的代码...
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if chatState == "ALL"
{
self.globalChat()
}else if chatState == "LOCAL"
{
self.localChat()
}
}
override func viewDidDisappear(animated: Bool) {
self.messageModels.removeAll()
tableView.reloadData()
ref.removeAllObservers()
}
func chatACTN()
{
if chatState == "ALL"
{
self.viewWillAppear(true)
}else if chatState == "LOCAL"
{
self.viewWillAppear(true)
}
}
func globalChat()
{
self.messageModels.removeAll()
tableView.reloadData()
let globalRef = ref.child("messages")
globalRef.keepSynced(true)
globalRef.queryLimitedToLast(100).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
if snapshot.exists()
{
let names = snapshot.value!["name"] as! String
let bodies = snapshot.value!["body"] as! String
let avatars = snapshot.value!["photo"] as! String
let time = snapshot.value!["time"] as! Int
let messageModel = MessageModel(name: names, body: bodies, avatar: avatars, date: time)
self.messageModels.append(messageModel)
self.messageModels.sortInPlace{ [=10=].date > .date }
}
self.tableView.reloadData()
})
}
func localChat()
{
self.messageModels.removeAll()
tableView.reloadData()
print("LOCAL")
}
问题是每次调用 globalChat()
时都会创建另一个新的观察者,这会导致多个观察者将相同的项目添加到 self.messageModels
。这就是为什么您在切换到全局状态时会多次看到数据。
既然你想在每次切换到全局时清除聊天并加载最后 100 个,那么当你切换到“本地”时保持观察者处于活动状态是没有意义的。
切换到 Local 时只需移除观察器,这应该可以解决您的问题。
来自 firebase 文档:
- (void) removeAllObservers
Removes all observers at the current reference, but does not remove any observers at child references.
removeAllObservers must be called again for each child reference where a listener was established to remove the observers.
因此,ref.removeAllObservers()
不会移除 ref.child("messages")
级别的观察者。
在 localChat
函数的开头使用 ref.child("messages").removeAllObservers
删除您在 globalChat
中创建的观察者,如果您只在这个级别处理这个观察者,但是如果您在同一级别上有更多,或者您认为将来可能会添加更多,最好和最安全的方法是删除您创建的特定观察者。为此,您应该使用从启动观察者返回的句柄。像这样修改您的代码:
var globalChatHandle : FIRDatabaseHandle?
func globalChat()
{
self.messageModels.removeAll()
tableView.reloadData()
ref.child("messages").keepSynced(true)
globalChatHandle = ref.child("messages").queryLimitedToLast(100).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
if snapshot.exists()
{
let names = snapshot.value!["name"] as! String
let bodies = snapshot.value!["body"] as! String
let avatars = snapshot.value!["photo"] as! String
let time = snapshot.value!["time"] as! Int
let messageModel = MessageModel(name: names, body: bodies, avatar: avatars, date: time)
self.messageModels.append(messageModel)
self.messageModels.sortInPlace{ [=10=].date > .date }
}
self.tableView.reloadData()
})
}
func localChat()
{
if globalChatHandle != nil {
ref.child("messages").removeObserverWithHandle(globalChatHandle)
}
self.messageModels.removeAll()
tableView.reloadData()
print("LOCAL")
}
并在 viewDidDisappear
方法中替换此
ref.removeAllObservers()
和
ref.child("messages").removeAllObservers()
我有一个用作 UITableView 的 SlackTextViewController 视图。我正在使用 public 字符串在 "states" 之间切换,允许它读取特定状态下的一组数据和另一状态下的另一组数据。问题是当我来回切换到原始状态时,它打印数据 2、3、4 次;和我来回一样多。我正在从 Firebase 服务器加载数据,我认为这可能是 Firebase 问题。这是我的代码...
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if chatState == "ALL"
{
self.globalChat()
}else if chatState == "LOCAL"
{
self.localChat()
}
}
override func viewDidDisappear(animated: Bool) {
self.messageModels.removeAll()
tableView.reloadData()
ref.removeAllObservers()
}
func chatACTN()
{
if chatState == "ALL"
{
self.viewWillAppear(true)
}else if chatState == "LOCAL"
{
self.viewWillAppear(true)
}
}
func globalChat()
{
self.messageModels.removeAll()
tableView.reloadData()
let globalRef = ref.child("messages")
globalRef.keepSynced(true)
globalRef.queryLimitedToLast(100).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
if snapshot.exists()
{
let names = snapshot.value!["name"] as! String
let bodies = snapshot.value!["body"] as! String
let avatars = snapshot.value!["photo"] as! String
let time = snapshot.value!["time"] as! Int
let messageModel = MessageModel(name: names, body: bodies, avatar: avatars, date: time)
self.messageModels.append(messageModel)
self.messageModels.sortInPlace{ [=10=].date > .date }
}
self.tableView.reloadData()
})
}
func localChat()
{
self.messageModels.removeAll()
tableView.reloadData()
print("LOCAL")
}
问题是每次调用 globalChat()
时都会创建另一个新的观察者,这会导致多个观察者将相同的项目添加到 self.messageModels
。这就是为什么您在切换到全局状态时会多次看到数据。
既然你想在每次切换到全局时清除聊天并加载最后 100 个,那么当你切换到“本地”时保持观察者处于活动状态是没有意义的。
切换到 Local 时只需移除观察器,这应该可以解决您的问题。
来自 firebase 文档:
- (void) removeAllObservers
Removes all observers at the current reference, but does not remove any observers at child references.
removeAllObservers must be called again for each child reference where a listener was established to remove the observers.
因此,ref.removeAllObservers()
不会移除 ref.child("messages")
级别的观察者。
在 localChat
函数的开头使用 ref.child("messages").removeAllObservers
删除您在 globalChat
中创建的观察者,如果您只在这个级别处理这个观察者,但是如果您在同一级别上有更多,或者您认为将来可能会添加更多,最好和最安全的方法是删除您创建的特定观察者。为此,您应该使用从启动观察者返回的句柄。像这样修改您的代码:
var globalChatHandle : FIRDatabaseHandle?
func globalChat()
{
self.messageModels.removeAll()
tableView.reloadData()
ref.child("messages").keepSynced(true)
globalChatHandle = ref.child("messages").queryLimitedToLast(100).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
if snapshot.exists()
{
let names = snapshot.value!["name"] as! String
let bodies = snapshot.value!["body"] as! String
let avatars = snapshot.value!["photo"] as! String
let time = snapshot.value!["time"] as! Int
let messageModel = MessageModel(name: names, body: bodies, avatar: avatars, date: time)
self.messageModels.append(messageModel)
self.messageModels.sortInPlace{ [=10=].date > .date }
}
self.tableView.reloadData()
})
}
func localChat()
{
if globalChatHandle != nil {
ref.child("messages").removeObserverWithHandle(globalChatHandle)
}
self.messageModels.removeAll()
tableView.reloadData()
print("LOCAL")
}
并在 viewDidDisappear
方法中替换此
ref.removeAllObservers()
和
ref.child("messages").removeAllObservers()