如何在我的聊天中获取并显示最后一条消息?
为了进行测试,我创建了四个用户,这些用户具有测试消息。现在,我只能为所有用户显示最新消息。我将颜色标记为红色。
我还使用Firebase保存消息并创建频道。
firebase中的结构如下:
- Chats
- channel id
- document data (then be stored ID and NAME of channel)
- collection thread
- documents data (then be stored MESSAGES)
我在频道中的结构:
struct Channel {
let id: String?
let name: String
init(name: String) {
id = nil
self.name = name
}
init?(document: DocumentSnapshot) {
let data = document.data()!
guard let name = data["name"] as? String else {
return nil
id = document.documentID
self.name = name
}
}
extension Channel: DatabaseRepresentation {
var representation: [String : Any] {
var rep = ["name": name]
if let id = id {
rep["id"] = id
}
return rep
}
}
我的结构消息,我使用MessageKit
:
struct Message: MessageType {
let id: String?
let content: String
let sentDate: Date
let sender: SenderType
var kind: MessageKind {
if let image = image {
return .photo(ImageMediaItem.init(image: image))
} else {
return .text(content)
}
}
var messageId: String {
return id ?? UUID().uuidString
}
var image: UIImage? = nil
var downloadURL: URL? = nil
init(profile: Profile, content: String) {
sender = Sender(id: profile.id, displayName: profile.name)
self.content = content
sentDate = Date()
id = nil
}
init?(document: QueryDocumentSnapshot) {
let data = document.data()
guard let sentDate = (data["created"] as? Timestamp)?.dateValue() else {
return nil
}
guard let senderID = data["senderID"] as? String else {
return nil
}
guard let senderName = data["senderName"] as? String else {
return nil
}
id = document.documentID
self.sentDate = sentDate
sender = Sender(id: senderID, displayName: senderName)
if let content = data["content"] as? String {
self.content = content
downloadURL = nil
} else if let urlString = data["url"] as? String, let url = URL(string: urlString) {
downloadURL = url
content = ""
} else {
return nil
}
}
}
扩展消息:DatabaseRepresentation {
var representation: [String : Any] {
var rep: [String : Any] = [
"created": sentDate,
"senderID": sender.senderId,
"senderName": sender.displayName
]
if let url = downloadURL {
rep["url"] = url.absoluteString
} else {
rep["content"] = content
}
return rep
}
}
要加载我的通道,请使用以下代码:
fileprivate func observeQuery() {
guard let query = query else { return }
listener = query.addSnapshotListener { (snapshot, error) in
guard let snapshot = snapshot else {
print("Error listening for channel updates: \(error?.localizedDescription ?? "No error")")
return
}
snapshot.documentChanges.forEach { (change) in
self.handleDocumentChange(change)
}
}
}
private func handleDocumentChange(_ change: DocumentChange) {
guard let channel = Channel(document: change.document) else {
return
}
switch change.type {
case .added:
addChannelToTable(channel)
case .modified:
updateChannelInTable(channel)
case .removed:
removeChannelFromTable(channel)
}
}
private func addChannelToTable(_ channel: Channel) {
guard !channels.contains(channel) else {
return
}
channels.append(channel)
channels.sort()
guard let index = channels.index(of: channel) else {
return
}
tableView.insertRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
}
private func updateChannelInTable(_ channel: Channel) {
guard let index = channels.index(of: channel) else {
return
}
channels[index] = channel
tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
}
private func removeChannelFromTable(_ channel: Channel) {
guard let index = channels.index(of: channel) else {
return
}
channels.remove(at: index)
tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
}
我认为需要更新我的频道结构。但是怎么做呢?
以及如何纠正加载并显示 firebase 中的最新消息?
如果需要更多信息,请告诉我,我会更新我的问题。
答案 0 :(得分:0)
如果问题是如何仅从Firestore获取最后一条消息,则需要定义如何确定最后一条消息是什么。这通常是通过时间戳完成的-最新的时间戳将成为最后一条消息。
问题的结构尚不清楚,所以让我提供一个简单的例子。
messages //collection
document_0 //documentID auto-generated
msg: "Last Message"
timestamp: "20191201"
document_1
msg: "First message"
timestamp: "20190801"
document_2
msg: "A message in the middle"
timestamp: "20191001"
如您所见,无论将它们写入Firestore的顺序如何,很显然带有最新时间戳(20191201)的消息都是最后一条消息。
要获取最后一条消息,我们需要执行以下两项操作的查询:
1)查询message节点,按降序排序,这会将最后一条消息置于“顶部”
2)将查询限制为1,这将获得该消息。
func readLastMessage() {
let ref = Firestore.firestore().collection("messages").order(by: "timestamp", descending: true).limit(to: 1)
ref.getDocuments(completion: { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
if let doc = snapshot.documents.first {
let docID = doc.documentID
let msg = doc.get("msg")
print(docID, msg)
}
})
}
和输出
Last Message
以上代码获取了最后一条消息,但是可以通过添加观察者而不是getDocuments进行扩展,其方式与出现新的最后一条消息时通知应用程序的方式相同。