Reputation: 93
I have a to-do list app and I want a checkmark to show up on the right (to signify that the task is complete) when the user clicks on the task. This is the code for the TableViewController:
import UIKit
class LoLFirstTableViewController: UITableViewController {
var tasks:[Task] = taskData
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 60.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
@IBAction func cancelToLoLFirstTableViewController(_ segue:UIStoryboardSegue) {
}
@IBAction func saveAddTask(_ segue:UIStoryboardSegue) {
if let AddTaskTableViewController = segue.source as? AddTaskTableViewController {
if let task = AddTaskTableViewController.task {
tasks.append(task)
let indexPath = IndexPath(row: tasks.count-1, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
let task = tasks[indexPath.row]
cell.task = task
if task.completed {
cell.accessoryType = UITableViewCellAccessoryType.checkmark;
} else {
cell.accessoryType = UITableViewCellAccessoryType.none;
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
var tappedItem = tasks[indexPath.row] as Task
tappedItem.completed = !tappedItem.completed
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
}
}
When I run it, nothing happens when I click on the task. What am I missing here? My Swift abilities leave a lot to be desired, unfortunately. Any help would be appreciated, thanks!
For reference, here is the code for the task class:
import UIKit
struct Task {
var name: String?
var points: Int
var completed: Bool
init(name: String?, points: Int, completed: Bool = false) {
self.name = name
self.points = points
self.completed = completed
}
}
Upvotes: 0
Views: 26
Reputation: 318944
The problem is with your didSelectRowAt
method where you update the task. A struct
is a value type. Any change normally makes a new copy. An array is also a value type. So when you update the tappedItem
variable, you end up with a new copy of the task but the one in the array isn't actually updated. So when the cell gets reloaded, the unmodified task is used to setup the cell.
Update your code as follows:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
var tappedItem = tasks[indexPath.row] as Task
tappedItem.completed = !tappedItem.completed
tasks[indexPath.row] = tappedItem // add this line
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
}
Upvotes: 1