在聊天应用程序中,为了跟踪每个聊天用户的最后消息和未读消息,当tableView单元退出队列时,我将在单元上附加一个.childChanged侦听器。当侦听器被触发时,我将更新每一行的chat label.text,以便进行相应的聊天。
什么时候应该删除这些侦听器,或者在我的情况下更新单元格中的聊天的最佳实践是什么?
程序的流程是什么?
class ChatTableViewCell: UITableViewCell {
@IBOutlet weak var lastMessageLabel: UILabel!
var chat: Chat! {
didSet{
self.updateUI()
}
}
func updateUI() {
self.chat.observeChildChanged(chat: self.chat, currentUserUID:user.userUID) { (lastMessage, unreadMessagesCount) in
if !lastMessage.isEmpty{
self.lastMessageLabel.text = lastMessage
}
if unreadMessagesCount > 0 {
self.lastMessageLabel.font = UIFont.boldSystemFont(ofSize: 16.0)
self.chatUnreadMessagesCount.text = "\(unreadMessagesCount)"
} else {
self.lastMessageLabel.font = UIFont.systemFont(ofSize: 15.0)
self.chatUnreadMessagesCount.text = ""
}
}
}
}
class MessagesViewController: UITableViewController {
override func viewDidLoad() {
//observe ~/users/uid
DDatabaseRReference.users(uid: uid).reference().observeSingleEvent(of: .value, with: { (snapshot) in
guard snapshot.exists() else {return}
if let userDict = snapshot.value as? [String : Any] {
self.currentUser = UserModel(dictionary: userDict)
self.userWasDownloaded = true //this will trigger the setter and start downloading chatId's of current user
}
})
}
var userWasDownloaded: Bool {
get {
return true
}
set {
self.fetchChatsIdsOf(currentUser: self.currentUser)
self.tableView.reloadData()
}
}
func fetchChatsIdsOf(currentUser: UserModel) {
//get chatIds of currentUser from ~/users/currentUser.userUID/chatIds
DDatabaseRReference.users(uid: currentUser.userUID).reference().child("chatIds").observe(.childAdded, with: { (snapshot) in
let chatUID = snapshot.key
if !self.chatIdsDownloaded.contains(chatUID) {
self.chatIdsDownloaded.append(chatUID)
}
})
}
//after chatIdsDownloaded is set,
//download the new chat for the last chat appended to chatIdsDownloaded array
var chatIdsDownloaded = [String]() {
didSet {
guard let chatID = chatIdsDownloaded.last else {return}
self.downloadNewChat(chatID: chatID)
}
}
func downloadNewChat(chatID: String) {
DDatabaseRReference.chats.reference().child(chatID).observeSingleEvent(of: .value, with: { (snapshot) in
......
self.currentUserChats.insert(chatChecked, at: 0)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatTableViewCell", for: indexPath) as! ChatTableViewCell
cell.chat = currentUserChats[indexPath.row]
return cell
}
}
chats // <- all chats in the app for all users in the app
-LOMVtcjOEOu2p1apMKV
chatUID: "-LOMVtcjOEOu2p1apMKV"
isGroupChat: true
lastMessage: "Katherine Gregory has joined the group"
lastUpdate: 1539761870.2237191
+users
IN4pgCS5NqQZZLpdmoz1KeDiFqj2
fcmToken: ""
firstName: "Alex"
userUID: "IN4pgCS5NqQZZLpdmoz1KeDiFqj2"
unreadMessagesCount: 5
users // <- all users in the app
IN4pgCS5NqQZZLpdmoz1KeDiFqj2
+chatIds
-LOMVtcjOEOu2p1apMKV: true
- name: ""
- email: ""
...etc发布于 2018-10-29 12:37:01
正如杰伊建议的那样,我在新下载的每一次聊天中都附加了.childChanged观察者。
但是,如果我转到firebase控制台并在ref路径上更新子节点的值,则并不总是会触发childChanged观察者。有时,它有效,有时它不可能是什么问题?
我在所有的行上都使用断点,当数据库中的值被更改时,它们都不会被击中。
例子:name:“亚历克斯”
更改:姓名:"John“
更新
这个答案是正确的,我忘记删除我以前的实现,在这个实现中分离prepareForReuse()中的侦听器。
var currentUserChats = [Chat]() {
didSet(newValue){
attachChildChangedObserverOn(chat: newValue)
}
}
var observersArray = [String: UInt]() // chatUID:handle
func attachChildChangedObserverOn(chat: Chat) {
var handle: UInt = 0
let ref = DDatabaseRReference.chats.reference().child(chat.chatUID).child("users").child(currentUser.userUID)
handle = ref.observe(.childChanged, with: {[weak self] (snapshot) in
self?.observersArray[chat.chatUID] = handle
print("snapshot.value is \(snapshot.value) and snapKey is \(snapshot.key)")
guard snapshot.exists() else {return}
let chatChanged = chat
var lastMessage = ""
var unreadMessagesCount = 0
var lastUpdate = 0.0
switch snapshot.key {
//case....
}
})
}发布于 2018-10-15 10:04:18
您可以检查是否为单元格添加了2个或更多的观察者。
在这里添加断点或print():
self.chat.observeChildChanged(chat: self.chat, currentUserUID: user.userUID) { (lastMessage, unreadMessagesCount) in {
//breakpoint or print("observeChildChanged")
...
}请重新使用你的手机。
发送新信息。
如果您有2条或更多条消息,这意味着您没有只设置一个观察者。
也许这种方法并不完美,但它可以帮助您(在添加新的之前删除旧的观察者):
var chat: Chat! {
didSet {
self.removeOldObserver()
self.updateUI()
}
}
func removeOldObserver() {
...
}https://stackoverflow.com/questions/52813356
复制相似问题