如何为可解码数据创建可重复使用的添加快照侦听器函数



在我的数据模型类中,我添加了四个快照侦听器来侦听文档更改。我注意到,我正在为每个集合复制代码,并且在添加快照侦听器时只更改数据的存储位置和数据类型。如何以优雅的方式消除这种重复?

class Model: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var notes: [Note] = []
    @Published var projects: [Project] = []
    @Published var notebooks: [Notebook] = []
    
    private var db = Firestore.firestore()
    
    init() {
        let _ = db.collection("tasks").whereField("userID", isEqualTo: Auth.auth().currentUser?.uid ?? "")
            .addSnapshotListener { querySnapshot, error in
                guard let documents = querySnapshot?.documents else {
                    print("No documents in 'tasks' collection")
                    return
                }
                self.tasks = documents.compactMap { queryDocumentSnapshot in
                    try? queryDocumentSnapshot.data(as: Task.self)
                }
            }
        let _ = db.collection("projects").whereField("userID", isEqualTo: Auth.auth().currentUser?.uid ?? "")
            .addSnapshotListener { querySnapshot, error in
                guard let documents = querySnapshot?.documents else {
                    print("No documents in 'projects' collection")
                    return
                }
                self.projects = documents.compactMap { queryDocumentSnapshot in
                    try? queryDocumentSnapshot.data(as: Project.self)
                }
            }
        let _ = db.collection("notes").whereField("userID", isEqualTo: Auth.auth().currentUser?.uid ?? "")
            .addSnapshotListener { querySnapshot, error in
                guard let documents = querySnapshot?.documents else {
                    print("No documents in 'notes' collection")
                    return
                }
                self.notes = documents.compactMap { queryDocumentSnapshot in
                    try? queryDocumentSnapshot.data(as: Note.self)
                }
            }
        let _ = db.collection("notebooks").whereField("userID", isEqualTo: Auth.auth().currentUser?.uid ?? "")
            .addSnapshotListener { querySnapshot, error in
                guard let documents = querySnapshot?.documents else {
                    print("No documents in 'notebooks' collection")
                    return
                }
                self.notebooks = documents.compactMap { queryDocumentSnapshot in
                    try? queryDocumentSnapshot.data(as: Notebook.self)
                }
            }
    }
}

我曾想过在数据库上创建一个集合的枚举,但我不清楚如何在没有详细if语句的情况下确定如何映射到正确的数据类型并检索正确的数组进行存储。

enum Collection: String, CaseIterable {
    case tasks = "tasks",
    case notes = "notes",
    case projects = "projects",
    case notebooks = "notebooks"
}
for collection in Collection.allCases {
    // Add snapshot listener
}

您可以尝试类似的方法(未经测试,我没有Firestore或您的模型(,使用CCD_ 1。根据您的需要调整示例代码。

enum Collection: String, CaseIterable {
    case tasks = "tasks"
    case notes = "notes"
    case projects = "projects"
    case notebooks = "notebooks"
}
class Model: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var notes: [Note] = []
    @Published var projects: [Project] = []
    @Published var notebooks: [Notebook] = []
    
    private var db = Firestore.firestore()
    
    func collect<T>(col: Collection, handler: @escaping ([T]) -> Void) { // <-- here
        let _ = db.collection(col.rawValue).whereField("userID", isEqualTo: Auth.auth().currentUser?.uid ?? "")
            .addSnapshotListener { querySnapshot, error in
                guard let documents = querySnapshot?.documents else {
                    print("No documents in collection: (col.rawValue)")
                    return handler([]) // <-- here
                }
                documents.compactMap { queryDocumentSnapshot in
                    let results = try? queryDocumentSnapshot.data(as: T.self)
                    handler(results) // <-- here
                }
            }
    }
    init() {
        collect(col: .tasks) { self.tasks = $0 }
        collect(col: .projects) { self.projects = $0 }
        collect(col: .notebooks) { self.notebooks = $0 }
        collect(col: .notes) { self.notes = $0 }
    }
}

最新更新