Reputation: 81
Model:
enum TaskType: Int, Codable {
case upcoming = 0
case inProgress
case testing
case completed
var title: String {
switch self {
case .upcoming:
return "Upcoming"
case .inProgress:
return "In Progress"
case .testing:
return "Testing"
case .completed:
return "Completed"
}
}
}
struct TasksModel: Encodable, Decodable {
var upcomingArray: [TaskInfo]
var inProgressArray: [TaskInfo]
var testingArray: [TaskInfo]
var completedArray: [TaskInfo]
}
struct TaskInfo: Codable, Equatable, Identifiable {
var id: String
var title: String
var description: String
var taskStatus: TaskType
var taskDate = Date()
}
VM:
class HomeVM: ObservableObject {
@Published var tasksArray: TasksModel
self.tasksArray = TasksModel.init(upcomingArray: [], inProgressArray: [], testingArray: [], completedArray: [])
}
So now that I could locate the record with received taskID and change the taskStatus, I need also to move the record from upcomingArray to inProgressArray. This is what I’m trying:
func inProgressSetTask(taskID: String) {
@StateObject var viewModel = HomeVM()
if let index = viewModel.tasksArray.upcomingArray.firstIndex(where: {$0.id == taskID}) {
// Update task status
viewModel.tasksArray.upcomingArray[index].taskStatus = .inProgress
// Need to remove from upcomingArray and append into inProgressArray
viewModel.tasksArray.upcomingArray.remove(at: index)
var lastIndex = viewModel.tasksArray.inProgressArray.last
viewModel.tasksArray.inProgressArray[lastIndex].append()
viewModel.save()
// End
} else {
…
Updating taskStatus above working fine but remove from one array into another is not.
This code above will repeat for each array after else. Appreciate any help.
Upvotes: 0
Views: 117
Reputation: 36383
you could try the following example code to achieve what you want:
(note, you should have @StateObject var viewModel = HomeVM()
outside of the func inProgressSetTask(taskID: String) {...}
or pass it in as a parameter)
EDIT-1: moving the function with all arrays into HomeVM
and assuming id
are unique.
func inProgressSetTask(taskID: String) {
print("InProgress Set ID# \(taskID)")
// with index, using `firstIndex`
if let index = viewModel.tasksArray.inProgressArray.firstIndex(where: {$0.id == taskID}) {
// do something with the index
viewModel.tasksArray.inProgressArray[index].title = "xxx"
}
// with TaskInfo, using `first`
if var taskInfo = viewModel.tasksArray.inProgressArray.first(where: {$0.id == taskID}) {
// do something with the taskInfo
taskInfo.title = "xxx"
}
}
With all arrays of TaskInfo, use the function setTaskFromAll(...)
in HomeVM
. For example: viewModel.setTaskFromAll(taskID: "1")
class HomeVM: ObservableObject {
@Published var tasksArray: TasksModel = TasksModel.init(upcomingArray: [], inProgressArray: [], testingArray: [], completedArray: [])
func setTaskFromAll(taskID: String) {
if let index = tasksArray.inProgressArray.firstIndex(where: {$0.id == taskID}) {
tasksArray.inProgressArray[index].title = "inProgress"
} else {
if let index = tasksArray.completedArray.firstIndex(where: {$0.id == taskID}) {
tasksArray.completedArray[index].title = "completed"
} else {
if let index = tasksArray.testingArray.firstIndex(where: {$0.id == taskID}) {
tasksArray.testingArray[index].title = "testing"
} else {
if let index = tasksArray.upcomingArray.firstIndex(where: {$0.id == taskID}) {
tasksArray.upcomingArray[index].title = "upcoming"
}
}
}
}
}
}
EDIT-2:
However, since you already have the "TaskType" of each array in the TaskInfo
struct, why not remove TasksModel
and use a single array of TaskInfo
in your HomeVM
. Like this:
class HomeVM: ObservableObject {
@Published var tasksArray: [TaskInfo] = [
TaskInfo(id: "1", title: "title1", description: "description1", taskStatus: .upcoming),
TaskInfo(id: "2", title: "title2", description: "description2", taskStatus: .inProgress)
// ....
]
func setTask(taskID: String, to taskType: TaskType) {
if let index = tasksArray.firstIndex(where: {$0.id == taskID}) {
tasksArray[index].taskStatus = taskType
}
}
func getAllTaskInfo(_ oftype: TaskType) -> [TaskInfo] {
return tasksArray.filter{$0.taskStatus == oftype}
}
}
and use it like this: viewModel.setTask(taskID: "1", to: .testing)
and viewModel.getAllTaskInfo(.inProgress)
EDIT-3: to remove from one array and append to another, using your TasksModel
scheme, use this:
class HomeVM: ObservableObject {
@Published var tasksArray: TasksModel = TasksModel(upcomingArray: [
TaskInfo(id: "1", title: "title1", description: "description1", taskStatus: .upcoming),
TaskInfo(id: "2", title: "title2", description: "description2", taskStatus: .upcoming)
], inProgressArray: [
TaskInfo(id: "3", title: "title3", description: "description3", taskStatus: .inProgress),
TaskInfo(id: "4", title: "title4", description: "description4", taskStatus: .inProgress)
], testingArray: [], completedArray: [])
func inProgressSetTask(taskID: String) {
if let index = tasksArray.upcomingArray.firstIndex(where: {$0.id == taskID}) {
// update task status
tasksArray.upcomingArray[index].taskStatus = .inProgress
// get the upcomingArray taskInfo
let taskInfo = tasksArray.upcomingArray[index]
// remove from upcomingArray
tasksArray.upcomingArray.remove(at: index)
// append to inProgressArray
tasksArray.inProgressArray.append(taskInfo)
} else {
// ...
}
}
}
Use it like this: viewModel.inProgressSetTask(taskID: "1")
As you can plainly see, you are much better-off with the EDIT-2
, you are repeating/duplicating things in EDIT-3
for no reason. There is no need for separate arrays for the different TaskType
, you already have this info in the TaskInfo
var taskStatus: TaskType
. With EDIT-2
, use viewModel.getAllTaskInfo(.inProgress)
to get all TaskInfo
of a particular type, just like it would be if you used a separate array.
Upvotes: 1
Reputation: 9695
You are attempting to compare a String
to a TaskInfo
, because the elements of an inProgressArray
are of type TaskInfo
. What you need to do is drill into the array and get to the .id
. That is simple to do. In the .first(where:)
, you simply pass a closure of $0.id == taskID
.
if let index = viewModel.tasksArray.inProgressArray.first(where: { $0.id == taskID } ) {
Upvotes: 0