Firestore NSArray 到 Swift.Array 匹配错误

Posted

技术标签:

【中文标题】Firestore NSArray 到 Swift.Array 匹配错误【英文标题】:Firestore NSArray to Swift.Array match error 【发布时间】:2019-05-18 17:54:03 【问题描述】:

我在使用 Firebase/Firestore SDK 时遇到了问题:

前提条件失败:NSArray 元素未能匹配 Swift Array 元素类型 预期 FIRQueryDocumentSnapshot 但发现 FIRQueryDocumentSnapshot:文件 /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1001.2.63.12/swift/stdlib/public/core/ArrayBuffer.swift,第 346 行 2019-05-18 19:46:00.020040+0200 App[25051:288337] 前提条件失败:NSArray 元素未能匹配 Swift Array 元素类型 预期的 FIRQueryDocumentSnapshot 但找到了 FIRQueryDocumentSnapshot:文件 /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1001.2.63.12/swift/stdlib/public/core/ArrayBuffer.swift,第 346 行

let listener = self.client
                .collection("countries/czechia/cities/\(id.rawValue)/venues")
                .addSnapshotListener( (snapshot, error) in
                    guard let docs = snapshot?.documents else 
                        observer.onError(error!)
                        return
                    

                    let arr: [Venue] = docs.compactMap  doc in // The code crashes on this line
                        do 
                            let decoded = try self.decoder.decode(Venue.self, from: doc.data())
                            return decoded
                         catch 
                            print(error)
                            return nil
                        
                    
                

【问题讨论】:

永远不要在警戒线中以这种方式注释类型:guard let docs: [QueryDocumentSnapshot] = snapshot?.documents else 。条件向下转换类型:guard let docs = snapshot?.documents as? [QueryDocumentSnapshot] else 是的,对不起,这是为了调试目的,我删除了它,无论如何代码仍然表现相同 试试let arr = docs.compactMap doc -> Venue? in 这没有帮助,当我开始迭代 docs 数组时,问题就出现了 【参考方案1】:

当您使用伞式框架技术时,此错误非常常见。 我得到“Precondition failed: NSArray element failed to match the Swift Array Element type 预期为 FIRQueryDocumentSnapshot,但发现 FIRQueryDocumentSnapshot bla bla bla bla...“尽管只有一个对静态框架的 Firebase 实例引用正常工作。

所以我不得不使用强大的 NSObject 功能,特别是键值编码协议。

检查一下……

let db = Firestore.firestore(app: firebase_instance)
    defaultsHelper.write(value: true, key: .isReceivingProspects)
    prospectosListener = db.collection("collection_name")
        .document("document_name")
        .collection("collection_name")
        .whereField("condition_parameter", arrayContains: "condition_value")
        .addSnapshotListener  querySnapshot, error in
            weak var _self = self
            
            guard let snapshot = querySnapshot else 
                print("Error fetching document: \(error!)")
                return
            
            
            // snapshot.documents or snapshot.documentChanges in a loop produces crash
            guard let documents = (snapshot as NSObject).value(forKey: "documentChanges") as? NSArray else  return 
            
            for document in documents 
                guard let object = document as? NSObject else  debugPrint("object was nil"); return 
                guard let type = object.value(forKey: "type") as? Int else  debugPrint("type was nil"); return 
                guard let docs = object.value(forKey: "document") as? NSObject else  debugPrint("document was nil"); return 
                guard let data = docs.value(forKey: "data") as? [String: Any] else  debugPrint("data was nil"); return 
                guard let fbModel = _self?.documentConverter.convertToNotificationModel(documentData: data) else 
                    debugPrint("fbModel was nil")
                    return
                
            
                switch type 
                    case 0: // Added
                        _self?.onAddedOrModifiedNotificationEvent(fbModel: fbModel)
                    case 1: // Modified
                        _self?.onAddedOrModifiedNotificationEvent(fbModel: fbModel)
                    case 2: // Removed
                        _self?.onDeleteNotificationEvent(fbModel: fbModel)
                default:
                    debugPrint("Another option")
                
            

【讨论】:

以上是关于Firestore NSArray 到 Swift.Array 匹配错误的主要内容,如果未能解决你的问题,请参考以下文章

将数据从 Firestore 映射到 Swift 中的结构 - IOS

使用 Swift 将数据上传到 Firestore 时出错

Swift & Firestore - 使用 .arrayUnion() 将字典附加到嵌套数组

NSArray 上的 Swift 内存泄漏

swift firestore将用户附加到数组 - 完成块

为啥我不能将从 Firestore 获取的值分配给 Swift 中的数组?