I have a DataModel with the following struct:
struct Task: Codable, Hashable, Identifiable {
var id = UUID()
var title: String
var completed = false
var priority = 2
}
In one my views, I populate a list with buttons based on each element of that DataModel, essentially a Task
.
I pass each task for the view like this:
ForEach(taskdata.filteredTasks(byPriority: byPriotity), id: \.id) { task in
TaskView(task: task)
}
On the view, I add each button as follow:
struct TaskView: View {
@EnvironmentObject private var taskdata: DataModel
@State var task: Task
var body: some View {
Button(action: {
task.completed.toggle() }) {
....
}
}
}
Now, when the user clicks on the button, if completed
was false, it makes it true. Simple. However, this doesn't update the DataModel, so I added the following to see if I could find the item in question and update it:
struct TaskView: View {
@EnvironmentObject private var taskdata: DataModel
@State var task: Task
@State var id: UUID // added this so I can also pass the ID and try to find it
var body: some View {
Button(action: {
task.completed.toggle()
if task.completed { // if it's completed, find it an update it.
//taskdata.tasks.first(where: { $0.id == id })?.completed = true
//taskdata.tasks.filter {$0.id == id}.first?.completed = true
/*if let index = taskdata.tasks.first(where: {$0.id == id}) {
print(index)
taskdata.tasks ????
}*/
}
}) {
....
}
All the commented code is what I have tried... I get different errors, from Cannot assign to property: function call returns immutable value
to cannot assign to property: 'first' is a get-only property
and a few other colorful Xcode errors.
How do I find the correct object on my DataModel and correctly update its .completed
to true (or false if it's clicked again).
Thank you
CodePudding user response:
You need to use Array >>> firstIndex
if let index = taskdata.tasks.firstIndex(where: {$0.id == id}) {
taskdata.tasks[index].completed = true
}
CodePudding user response:
There is another way for your problem using a function in extension like this custom update function:
extension Array {
mutating func update(where condition: (Element) -> Bool, with newElement: (Element) -> Element) {
if let unwrappedIndex: Int = self.firstIndex(where: { value in condition(value) }) {
self[unwrappedIndex] = newElement(self[unwrappedIndex])
}
}
}
use case:
taskdata.tasks.update(where: { element in element.id == id }, with: { element in
var newElement: Task = element
newElement.completed = true
return newElement
})