'How can I create a generic function that listens for firestore updates?
In my data model class I have two arrays that I initialise as empty arrays. Within the class initialiser I add a snapshot listener that listens to the arrays relevant collection. Both models conform to the Codable protocol so that I can map the fetched firestore data. The ModelData class is going to contain more arrays so to have these snapshot listener blocks of code in the initialiser feels like I am violating the DRY principle.
final class ModelData: ObservableObject {
@Published var tasks: [Task] = []
@Published var projects: [Project] = []
let db = Firestore.firestore()
init() {
db
.collection("tasks")
.addSnapshotListener { querySnapshot, error in
if let documents = querySnapshot?.documents {
self.tasks = documents.compactMap { queryDocumentSnapshot in
try? queryDocumentSnapshot.data(as: Task.self)
}
}
}
db
.collection("projects")
.addSnapshotListener { querySnapshot, error in
if let documents = querySnapshot?.documents {
self.projects = documents.compactMap { queryDocumentSnapshot in
try? queryDocumentSnapshot.data(as: Project.self)
}
}
}
}
}
I would like to know if it is possible to remove the code from the initialiser and make it into a generic function? Is the following function signature below a step in the right direction?
func listen<T: Codable>(_ array: [T]) {
...
}
Update #1
I have the generic listen function working by passing in the type and then on the specific sections where I map data or list a collection I have a condition statement that checks the type. I still feel as though I am repeating myself when mapping the data. Could the complexity of this function be minimised in anyway?final class ModelData: ObservableObject {
@Published var tasks: [Task] = []
@Published var projects: [Project] = []
let db = Firestore.firestore()
init() {
listen(type: Task.self)
listen(type: Project.self)
}
func listen<T: Codable>(type: T.Type) {
db
.collection(type == Task.self ? "tasks" : "projects")
.whereField("userID", isEqualTo: "tXHIUJ6YUCORv6BWGZaxsYzvQBY2")
.addSnapshotListener { querySnapshot, error in
if let documents = querySnapshot?.documents {
if type == Task.self {
self.tasks = documents.compactMap { queryDocumentSnapshot in
try? queryDocumentSnapshot.data(as: T.self) as? Task
}
} else {
self.projects = documents.compactMap { queryDocumentSnapshot in
try? queryDocumentSnapshot.data(as: T.self) as? Project
}
}
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
