SwiftUI+Firestore开发:String无法转Workout模型对象如何解决
解决方案
你当前拿到的是Workout对应的Firestore文档ID字符串,并不是Workout模型实例,需要拿着这个ID到训练集合中拉取完整文档后解析为Workout对象,具体实现步骤如下:
步骤1:确认Workout模型遵守Codable协议
Firestore原生支持Codable协议解析文档,首先确保你的自定义模型符合要求,示例如下:
import FirebaseFirestoreSwift struct Workout: Codable, Identifiable { @DocumentID var id: String? // 自动映射文档ID // 下方补充你自己定义的所有训练字段,比如: let title: String let duration: Int let calorie: Int let ownerUid: String }
步骤2:修改拉取逻辑,批量获取训练数据
推荐使用批量查询的方式替代循环单次查询,性能更高,修改后的fetchFavoriteWorkouts代码如下:
func fetchFavoriteWorkouts(){ guard let currentUid = AuthViewModel.shared.userSession?.uid else { return } // 加[weak self]避免循环引用导致内存泄漏 COLLECTION_USERS.document(currentUid).collection("user-feed").addSnapshotListener { [weak self] snapshot, error in guard let self = self, let documents = snapshot?.documents, error == nil else { return } // 每次更新先清空旧数据,避免重复添加 self.workouts.removeAll() // 收集所有收藏的训练ID let allWorkoutIDs = documents.flatMap { doc in doc.get("workouts") as? [String] ?? [] } // 去重避免同一个训练被多次拉取 let uniqueWorkoutIDs = Array(Set(allWorkoutIDs)) // 批量拉取所有对应的训练文档 COLLECTION_WORKOUTS.whereField(FieldPath.documentID(), in: uniqueWorkoutIDs).getDocuments { querySnapshot, error in guard let docs = querySnapshot?.documents, error == nil else { return } // 解析为Workout模型 let fetchedWorkouts = docs.compactMap { try? $0.data(as: Workout.self) } // 赋值给数据源数组 self.workouts = fetchedWorkouts } } }
注意事项
- 不要使用强制解包(比如代码中的
as!、snapshot!),改为可选绑定可以避免空值导致的App崩溃 - 如果你的训练数据会实时更新,可以把批量拉取的
getDocuments也换成addSnapshotListener,实现训练内容的实时同步 - 单次
in查询最多支持10个ID,如果你的用户收藏的训练ID超过10个,需要拆分ID数组分批查询
内容的提问来源于stack exchange,提问作者Jake12345
相关产品推荐
相关产品推荐

