使用 FirestoreDecoder 解码 Firestore 文档时 UI 冻结
Posted
技术标签:
【中文标题】使用 FirestoreDecoder 解码 Firestore 文档时 UI 冻结【英文标题】:UI freezes when using FirestoreDecoder to decode Firestore documents 【发布时间】:2021-06-17 14:26:21 【问题描述】:我正在从 Firestore 获取数据,映射文档并使用 FirestoreDecoder 对每个文档进行解码。但是,解码文档会暂时冻结 UI。在后台线程上运行代码没有区别。如何防止 UI 在解码过程中冻结?
let collection = Firestore.firestore().collection("roll_groups")
collection.addSnapshotListener (snapshot, error) in
if let error = error
print("Error fetching roll groups: \(error.localizedDescription)")
else if let snapshot = snapshot
DispatchQueue.global(qos: .background).async
let rollGroups = snapshot.documents.map doc -> RollGroup? in
do
let rollGroup = try FirestoreDecoder().decode(RollGroup.self, from: doc.data())
return rollGroup
catch
print("Error decoding roll groups: \(error)")
return nil
DispatchQueue.main.async
completion(rollGroups)
【问题讨论】:
对我来说看起来不错。如果可以的话,我会使用 Instruments 中的 Time Profiler 来查明瓶颈。这可能是完成处理程序本身发生的事情。 @BradleyMackey 谢谢,会的!奇怪的是,如果我完全删除完成处理程序,它仍然会冻结,所以我认为这与此无关:( 如果您删除完成处理程序,则不会进行任何解码但 UI 仍然冻结? 您不需要 DispatchQueue.main.async,而且我在您的代码中看不到任何 UI 调用。在 Firebase 闭包中,网络都是在后台线程上完成的,UI 调用是在主线程上自动完成的,因此它永远不会干扰 UI。由于您使用的是第三方库,因此问题可能就在那里,并且与 Firebase 无关。 我会放弃这个库,因为 IMO 这些第三方依赖项应该用于更大的事情,比如路线图和数据库接口。如果您使用它的唯一原因是抽象 Firestore 时间戳对象的编码/解码,那么我什至不会三思而后行摆脱它。您可以将 Firestore 时间戳转换为可与Codable
一起使用的内容,例如 unix-timestamp(在 Swift 中为 UInt64
)、ISO-8601 日期 (hackingwithswift.com/example-code/language/…) 等。
【参考方案1】:
可能的解决方案
看这段代码似乎一切正常,我只是想确认您的方法的completion
绝对是@escaping: completion()
否则可能会导致此问题
另外,可能值得将实际的 DB 调用 (collection.addSnapshotListener)
包含在
DispatchQueue.global(qos: .background).async
只是看看这是否会有所作为,理论上它不应该,但仍然值得一试
【讨论】:
以上是关于使用 FirestoreDecoder 解码 Firestore 文档时 UI 冻结的主要内容,如果未能解决你的问题,请参考以下文章