如何创建一个函数来搜索 ID、定位和更改此记录的一个字段?

How can I create a function to search for an ID, locate and change one field of this record?

型号:

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()
}

虚拟机:

class HomeVM: ObservableObject {
            
      @Published var tasksArray: TasksModel
                    
      self.tasksArray = TasksModel.init(upcomingArray: [], inProgressArray: [], testingArray: [], completedArray: [])
}

现在我可以找到具有接收到的 taskID 的记录并更改 taskStatus,我还需要将记录从 comcomingArray 移动到 inProgressArray。这就是我正在尝试的:

func inProgressSetTask(taskID: String) {
    @StateObject var viewModel = HomeVM()
    if let index = viewModel.tasksArray.upcomingArray.firstIndex(where: {[=12=].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 {

更新上面的 taskStatus 工作正常,但从一个数组移除到另一个数组则不行。

上面的代码将在 else 之后对每个数组重复。感谢任何帮助。

您正试图将 StringTaskInfo 进行比较,因为 inProgressArray 的元素属于 TaskInfo 类型。您需要做的是钻入数组并到达 .id。这很容易做到。在 .first(where:) 中,您只需传递 [=17=].id == taskID.

的闭包
    if let index = viewModel.tasksArray.inProgressArray.first(where: { [=10=].id == taskID } ) {

您可以尝试以下示例代码来实现您想要的:
(请注意,您应该在 func inProgressSetTask(taskID: String) {...} 之外添加 @StateObject var viewModel = HomeVM() 或作为参数传入)

EDIT-1:将包含所有数组的函数移动到 HomeVM 并假设 id 是唯一的。

func inProgressSetTask(taskID: String) {
    print("InProgress Set ID# \(taskID)")
    
    // with index, using `firstIndex`
    if let index = viewModel.tasksArray.inProgressArray.firstIndex(where: {[=10=].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: {[=10=].id == taskID}) {
        // do something with the taskInfo
        taskInfo.title = "xxx"
    }

}

对于TaskInfo的所有数组,使用HomeVM中的函数setTaskFromAll(...)。例如: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: {[=11=].id == taskID}) {
            tasksArray.inProgressArray[index].title = "inProgress"
        } else {
            if let index = tasksArray.completedArray.firstIndex(where: {[=11=].id == taskID}) {
                tasksArray.completedArray[index].title = "completed"
            } else {
                if let index = tasksArray.testingArray.firstIndex(where: {[=11=].id == taskID}) {
                    tasksArray.testingArray[index].title = "testing"
                } else {
                    if let index = tasksArray.upcomingArray.firstIndex(where: {[=11=].id == taskID}) {
                        tasksArray.upcomingArray[index].title = "upcoming"
                    }
                }
            }
        }
    }
    
}

编辑-2:

但是,由于您已经在 TaskInfo 结构中拥有每个数组的“TaskType”,为什么不删除 TasksModel 并在 HomeVM 中使用 TaskInfo 的单个数组。像这样:

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: {[=12=].id == taskID}) {
            tasksArray[index].taskStatus = taskType
        }
    }

    func getAllTaskInfo(_ oftype: TaskType) -> [TaskInfo] {
        return tasksArray.filter{[=12=].taskStatus == oftype}
    }
}

并像这样使用它:viewModel.setTask(taskID: "1", to: .testing)viewModel.getAllTaskInfo(.inProgress)

EDIT-3:要从一个数组中删除并附加到另一个数组中,使用您的 TasksModel 方案,请使用:

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: {[=13=].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 {
            // ...
        }
    }
    
}

这样使用:viewModel.inProgressSetTask(taskID: "1")

如你所见,你在EDIT-2中better-off,无缘无故在EDIT-3中repeating/duplicating。不需要为不同的 TaskType 使用单独的数组,您已经在 TaskInfo var taskStatus: TaskType 中获得了此信息。使用 EDIT-2,使用 viewModel.getAllTaskInfo(.inProgress) 获取特定类型的所有 TaskInfo,就像使用单独的数组一样。