In my app I have a task and a note object that both can contain an array of tags. The tasks and notes are fetched and stored in their respective stores. I pass these two classes down as environment objects. When a user is editing a task or a note, depending on the type, they go to the TaskEditView or NoteEditView. They can add a new tag, however if a tag already exists it will add that existing tag to the object. Because the tags are spread across two different stores how can I merge the two arrays and find if the tag exists without duplicating code?
struct Task: Identifiable {
var id: String = UUID().uuidString
var tags: [Tag] = []
// Other task properties
}
struct Note: Identifiable {
var id: String = UUID().uuidString
var tags: [Tag] = []
// Other note properties
}
struct Tag {
var title: String
var color: Color
}
class TaskStore: ObservableObject {
@Published var tasks = [Task]()
// Other TaskStore properties and functions
}
class NoteStore: ObservableObject {
@Published var notes = [Note]()
// Other NoteStore properties and functions
}
The only solution I have found is to pass the NoteStore and TaskStore down as environment objects and then map the tasks and notes arrays into a combined array of tag objects. However, I do not like this because I have to duplicate this code for the NoteEditView, TaskEditView and any other edit view of an object that contains a list of tags as a property. At the same time I have to pass every store that has objects that contain tags. Ideally I would want to create a class called TagStore that uses combine that subscribes to these two arrays.
let tags = [taskStore.tasks.flatMap { $0.tags }, noteStore.notes.flatMap { $0.tags }]
.flatMap { $0 }
if let tag = tags.first(where: { $0.title == "History" }) {
// Tag already exists
}
CodePudding user response:
Normally there is a single store environment object so I would recommend merging your objects:
class Store: ObservableObject {
@Published var tasks: [Task] = []
@Published var notes: [Note] = []
// now you can have funcs that work on tasks and notes, e.g.
//var allTags: [Tag] {
//}
// because any change to tasks or notes will fire objectWillChange, these computed vars don't need to be published.
}
Take a look at the Fruta sample's Store object for ideas, it's named Model
.