我们正在使用Firestore构建实时聊天应用程序。我们需要处理不存在Internet连接的情况。基本消息发送代码如下所示:
let newMsgRef = database.document(“/users/\(userId)/messages/\(docId)“)
newMsgRef.setData(payload) { err in
if let error = err {
// handle error
} else {
// handle OK
}
}
连接设备后,一切正常。未连接设备时,不会调用回调,并且我们也不会得到错误状态。
当设备重新联机时,记录将出现在数据库和回调触发器中,但是我们无法接受此解决方案,因为与此同时应用程序可能已终止,因此我们将永远无法获得回调并能够进行设置发送消息的状态。
我们认为禁用离线持久性(默认情况下处于启用状态)会使它立即触发故障回调,但出乎意料-不会。
我们还尝试添加一个超时,在此之后发送操作将被视为失败,但是由于Firestore使用其队列,因此无法恢复设备恢复联机时取消消息传递的方式,这会导致更多混乱,因为消息是在接收方发送,而我在发送方无法处理。
如果我们可以减少超时时间(这可能是一个很好的解决方案),我们会迅速获得成功/失败状态,但Firebase不会提供此类设置。
内置脱机缓存可能是另一种选择,我可以将所有写入视为成功并依靠Firestore同步机制,但是如果应用程序在脱机期间终止,则消息不会传递。
最终,我们需要一个一致的反馈机制,该机制将触发回调,或提供一种监视队列中消息的方式,等等。因此,我们可以确定消息是否已发送以及何时发送。
答案 0 :(得分:2)
仅当在服务器上写入(或拒绝)数据时,才调用Firestore的完成回调。没有网络连接时没有回调,因为这是Firestore SDK的正常情况。
您最好的选择是检测是否存在另一种网络连接,然后相应地更新UI。一些相关的搜索结果:
或者,您可以检查使用Firestore的内置元数据来确定是否已传递邮件。如documentation on events for local changes所示:
检索到的文档具有
metadata.hasPendingWrites
属性,该属性指示文档是否具有尚未写入后端的本地更改。您可以使用此属性来确定快照侦听器收到的事件的来源:db.collection("cities").document("SF") .addSnapshotListener { documentSnapshot, error in guard let document = documentSnapshot else { print("Error fetching document: \(error!)") return } let source = document.metadata.hasPendingWrites ? "Local" : "Server" print("\(source) data: \(document.data() ?? [:])") }
与此同时,您还可以在用户界面中正确显示消息