我无法将在基于Swift IOS的聊天应用程序中从Firestore数据库中检索到的文档追加到“ messages”变量中,在追加后,如代码中所示配置了表格单元格,出现以下错误 错误
Cannot convert value of type '[QueryDocumentSnapshot]' to expected argument type 'DocumentSnapshot'
代码
var messages: [DocumentSnapshot]! = []
func configuredatabase ()
{
db.collection("messages").document("hello").collection("newmessages").document("2").collection("hellos").document("K").collection("messages").addSnapshotListener { querySnapshot, error in
guard let documents = querySnapshot?.documents else {
print("Error fetching documents: \(error!)")
return
}
//here is the error
self.messages.append(documents)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Dequeue cell
let cell = self.clientTable .dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)
// Unpack message from Firebase DataSnapshot
let messageSnapshot = self.messages![indexPath.row]
guard let message = messageSnapshot as? [String:String] else { return cell }
let name = message[Constants.MessageFields.name] ?? ""
if let imageURL = message[Constants.MessageFields.imageURL] {
if imageURL.hasPrefix("gs://") {
Storage.storage().reference(forURL: imageURL).getData(maxSize: INT64_MAX) {(data, error) in
if let error = error {
print("Error downloading: \(error)")
return
}
DispatchQueue.main.async {
cell.imageView?.image = UIImage.init(data: data!)
cell.setNeedsLayout()
}
}
} else if let URL = URL(string: imageURL), let data = try? Data(contentsOf: URL) {
cell.imageView?.image = UIImage.init(data: data)
}
cell.textLabel?.text = "sent by: \(name)"
} else {
let text = message[Constants.MessageFields.text] ?? ""
cell.textLabel?.text = name + ": " + text
cell.imageView?.image = UIImage(named: "ic_account_circle")
if let photoURL = message[Constants.MessageFields.photoURL], let URL = URL(string: photoURL),
let data = try? Data(contentsOf: URL) {
cell.imageView?.image = UIImage(data: data)
}
}
return cell
}
答案 0 :(得分:0)
将self.messages.append(documents)
替换为self.messages.append(contentsOf: documents)
第一种方法采用单个元素,第二种方法采用您所用的集合。 https://developer.apple.com/documentation/swift/array/3126937-append https://developer.apple.com/documentation/swift/array/3126939-append
答案 1 :(得分:0)
var messages: [[String: Any]] = []
db.collection("messages").document("hello").collection("newmessages").document("2").collection("hellos").document("K").collection("messages").addSnapshotListener { querySnapshot, error in
guard let documents = querySnapshot?.documents else {
print("Error fetching documents: \(error!)")
return
}
for doc in documents {
self.messages.append(doc.data())
}
}
答案 2 :(得分:0)
虽然还有其他两个很好的答案,但两者之间可能会有一些困惑
FIRDocumentSnapshot (Note: renamed to DocumentSnapshot)
要获取特定文档时返回以下内容:someDoc.getDocument(
和
FIRQuerySnapshot (Note: renamed to QuerySnapshot)
当将观察者添加到集合中或正在检索一系列文档时,返回哪个:someCollection.getDocuments,然后QuerySnapshot中的每个文档都是谨慎的FIRQueryDocumentSnapshot(重命名为QueryDocumentSnapshot)。 (例如,遍历QuerySnapshot以获得子QueryDocumentSnapshot)
请注意,如果文档不存在,DocumentSnapshot的data属性可能返回nil,因此可以对它进行.exists测试。而QueryDocumentSnapshot永远不会为零(始终存在,因为没有返回删除的数据)。
在问题中,观察者被添加到具有以下内容的集合中
.collection("messages").addSnapshotListener
因此,返回的数据是QuerySnapshot并将其存储为var,则需要匹配var类型
var messagesQuerySnapshot: QuerySnapshot!
然后在侦听器中
db.collection("messages")...addSnapshotListener { querySnapshot, error in
messagesQuerySnapshot = querySnapshot
但是,我不建议这样做。
我建议使用可以从Firestore检索的数据进行初始化并将其存储在数组中的消息类。
class MessagesClass {
var msg_id = ""
var msg = ""
var from = ""
convenience init(withQueryDocSnapshot: QueryDocumentSnapshot) {
//init vars from the document snapshot
}
}
然后是一个var类数据源数组来保存它们
var messagesArray = [MessageClass]()
然后编写代码以读取消息,创建消息对象并将其添加到dataSource数组
db.collection("messages")...getDocuments { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
for doc in snapshot.documents {
let aMsg = MessageClass(withQueryDocSnapshot: doc)
self.messagesArray.append(aMsg)
}
}
注意:我们不在这里添加侦听器,而是一次获取文档。如果要添加侦听器以监视正在添加,更改或删除的用户,则需要其他代码来检测更改。
请参阅Viewing Changes Between Snapshots上的Firebase文档