Bob F.
Bob F.

Reputation: 93

Checkmarks not appearing when tapped

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

Answers (1)

rmaddy
rmaddy

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

Related Questions