Firestore集合获取报错:闭包传参错误及类型转换问题
解决Firestore数据读取的两个错误
1. "Trailing closure passed to parameter of type 'FirestoreSource' that does not accept a closure" 错误修复
这个错误是因为调用getDocuments()时多写了一对括号。Firestore的getDocuments方法第一个可选参数是source: FirestoreSource?,写getDocuments()相当于传入默认nil作为source参数,随后把闭包传递给了不接受闭包的参数位置,导致类型不匹配。
修复方式:去掉getDocuments后的括号,直接绑定闭包:
portfolioCollection.getDocuments { (querySnapshot, err) in // 闭包逻辑 }
2. "Value of type 'Any' has no subscripts" 错误修复
这个错误源于myDic数组未声明明确类型,默认被推断为[Any],遍历元素时无法用下标访问字典键值。此外代码中未显式声明myDic,需指定其为字典数组类型。
修复步骤:
- 显式声明
myDic为[[String: Any]]类型,确保每个元素都是字符串键的字典 - 初始化
Property时,将字典中的Any类型转换为对应属性需要的类型(如String、Int等),同时修正代码中size与price的参数顺序错误
修正后的完整代码
private func getPortfolioItems() { guard let currentUser = Auth.auth().currentUser else { return } let userID = currentUser.uid print("User ID: \(userID)") let userRef = db.collection("users").document(userID) let portfolioCollection = userRef.collection("portfolio") var portfolioArray = [Property]() var myDic: [[String: Any]] = [] // 显式声明字典数组类型 portfolioCollection.getDocuments { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") return } guard let documents = querySnapshot?.documents else { return } for document in documents { let dictionary = document.data() print(dictionary["property_address"] ?? "No address") myDic.append(dictionary) print(myDic.count) } // Firestore请求是异步的,必须在闭包内处理数据 myDic.forEach { dictionary in print(dictionary) // 可选绑定转换类型,避免强制解包崩溃 guard let address = dictionary["property_address"] as? String, let bath = dictionary["property_baths"] as? Int, let room = dictionary["property_beds"] as? Int, let price = dictionary["property_price"] as? Double, // 根据实际类型调整 let size = dictionary["property_size"] as? String else { // 根据实际类型调整 return } // 修正size和price的参数顺序 let property = Property(address: address, bath: bath, room: room, size: size, price: price) portfolioArray.append(property) } // 更新UI需切换到主线程 DispatchQueue.main.async { // 此处执行UI更新操作 } } }
额外注意事项
- 避免强制解包
querySnapshot!,用guard let/if let处理,防止崩溃 - Firestore请求是异步操作,所有数据处理必须在闭包内完成,闭包外访问
portfolioArray/myDic只会拿到初始空值 - 初始化
Property时,需根据你的结构体/类的实际参数类型调整转换逻辑 - 更新UI必须切换到主线程,Firestore闭包默认在后台线程执行
内容的提问来源于stack exchange,提问作者xplayz
相关产品推荐
相关产品推荐

