At the beginning of the application, I can successfully see the todo array. However, after moving a todo item to the "in progress" or "done" status, when I return to the "todo" status again, the todoGoals array is not visible on the screen. Only the section I last clicked on is visible.
HomeViewModel :
import Foundation
protocol HomeViewModelInterface {
var view: HomeScreenInterface? { get set }
func viewDidLoad()
func viewToDoGoals()
func viewInProgressGoals()
func viewDoneGoals()
}
final class HomeViewModel {
weak var view: HomeScreenInterface?
var progressSections: [String] = ["To Do","In Progress","Done"]
lazy var toDoGoals: [ToDoModel] = [
ToDoModel(title: "ToDo 1"),
ToDoModel(title: "Todo 2"),
ToDoModel(title: "ToDo 3")
]
lazy var inProgressGoals: [ToDoModel] = [
ToDoModel(title: "Progress 1"),
ToDoModel(title: "Progress 2"),
ToDoModel(title: "Progress 3")
]
lazy var done: [ToDoModel] = [
ToDoModel(title: "Done 1"),
ToDoModel(title: "Done 2"),
ToDoModel(title: "Done 3")
]
}
extension HomeViewModel: HomeViewModelInterface {
func viewDidLoad() {
view?.configureVC()
view?.configureCollectionView()
view?.configureTableView()
}
func viewToDoGoals() {
self.view?.updateTableView(with: self.toDoGoals)
print("View todo")
}
func viewInProgressGoals() {
self.view?.updateTableView(with: self.inProgressGoals)
print("View progress")
}
func viewDoneGoals() {
self.view?.updateTableView(with: self.done)
print("View Done.")
}
}
Home Screen : The protocol function where I update the tableview is here.
protocol HomeScreenInterface: AnyObject {
func configureVC()
func configureCollectionView()
func configureTableView()
func updateTableView(with goals: [ToDoModel])
}
final class HomeScreen: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
viewModel.view = self
viewModel.viewDidLoad()
}
extension HomeScreen: HomeScreenInterface {
func configureVC() {
title = "To Do ✅"
view.backgroundColor = .systemBackground
}
// Update TableView Array
func updateTableView(with goals: [ToDoModel]) {
viewModel.toDoGoals = goals
DispatchQueue.main.async {
self.goalsTableView.reloadData()
}
}
}
}
TableView Delegate and DataSource Methods:
extension HomeScreen: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.toDoGoals.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: GoalsCells.reuseIdentifier, for: indexPath) as? GoalsCells else {
return UITableViewCell()
}
cell.delegate = self
let goals = viewModel.toDoGoals[indexPath.row]
cell.setGoalCell(goal: goals.title, checked: goals.isComplete)
return cell
}
}
CollectionView Delegate and DataSource Methods:
extension HomeScreen: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ProgressCells.reuseIdentifier, for: indexPath) as? ProgressCells else {
return UICollectionViewCell()
}
cell.setCell(progress: viewModel.progressSections[indexPath.item])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch indexPath.item {
case 0: // To Do
self.viewModel.viewToDoGoals()
case 1: // In Progress
self.viewModel.viewInProgressGoals()
case 2: // Done
self.viewModel.viewDoneGoals()
default:
break
}
}
}
Model :
import Foundation
struct ToDoModel {
let title: String
let isComplete: Bool
init(title: String, isComplete: Bool = false) {
self.title = title
self.isComplete = isComplete
}
func completeToggled() -> ToDoModel {
return ToDoModel(title: title, isComplete: !isComplete)
}
}
This is because with your current logic, whenever a user taps on "In Progress" or "Done" cell, that tapping event overwrites toDoGoals
property.
extension HomeScreen: HomeScreenInterface {
//...
// Update TableView Array
func updateTableView(with goals: [ToDoModel]) {
viewModel.toDoGoals = goals // Here: toDoGoals is updated every time user taps on other cells.
DispatchQueue.main.async {
self.goalsTableView.reloadData()
}
}
}
}
So the original elements inside toDoGoals
array are eliminated by tapping other cells. I think you can handle this issue in two ways.
enum
to indicate what type of tasks you want to show and let the table view show the relevant [ToDoModel]
property.Hope this can help you to debug this issue!