How to save the state of the checkbox to core data

2019-09-16 23:12发布

问题:

**I'm not a good English speaker. Please forgive me for my awkward English.

I'm working on a to do list project using checkbox. I cannot find a way to save the state of the checkbox to core data

This is a part of the code I use right now. Tasksis the Entity (class definition) and it has isMarked as a Boolean Attribute. (I cut a lot to make it simple so if you find something strange in the code please write a comment)

import UIKit
import CoreData

var toDolist: [Tasks] = []

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{


    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(toDoTable)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBOutlet weak var toDoTable: UITableView!

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return toDolist.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell
        cell.box.setImage(#imageLiteral(resourceName: "uncheckedbox"), for: .normal)

        let task = toDolist[indexPath.row]

        return cell
    }

    func getData(){
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        do{
            toDolist = try context.fetch(Tasks.fetchRequest())
        }catch{
            print("fetching failed")
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        getData()
        toDoTable.reloadData()
    }

}


class CustomTableViewCell: UITableViewCell {
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    @IBOutlet weak var box: CheckBox!
    @IBOutlet weak var taskLbl: UILabel!
}

class CheckBox{
    var isChecked: Bool = false{
        didSet{
            if isChecked == true{
                self.setImage(#imageLiteral(resourceName: "checkedbox"), for: .normal)
            }else{
                self.setImage(#imageLiteral(resourceName: "uncheckedbox"), for: .normal)
            }
        }
    }

    override func awakeFromNib(){
        self.addTarget(self, action: #selector(self.buttonClicked(_:)), for: .touchUpInside)
        self.isChecked = false
    }

    func buttonClicked(_ sender: UIButton){
        if sender == self{
            if isChecked == true{
                isChecked = false
            }else{
                isChecked = true
            }
        }
    }
}

How can I solve this by adding some code to it? Or do I have to change all the code above?

回答1:

Simple solution:

  • Remove the subclass of UIButton and revert the class of the button to UIButton.
  • In Interface Builder assign the images checkedbox and uncheckedbox to the button for states selected and default. The images are displayed automatically depending on the isSelected property of the button. That avoids completely to update the images in code.

  • The class CustomTableViewCell got the property task and the IBAction which must be connected to Touch Up Inside of the button. The property isSelected of the task must be changed to the name of the attribute of the NSManagedObject

    class CustomTableViewCell: UITableViewCell {
    
        @IBOutlet weak var box: UIButton!
        @IBOutlet weak var taskLbl: UILabel!
    
        var task : Tasks! {
            didSet {
                box.isSelected = task.isSelected
                taskLbl.text = // update the label
            }
        }
    
        @IBAction func buttonClicked(_ sender: UIButton)
        {
            let selected = !sender.isSelected
            sender.isSelected = selected
            task.isSelected = selected
            // save the context if needed
        }
    
    }
    
  • In cellForRowAt just add the line to assign the task

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell
        let task = toDolist[indexPath.row]
        cell.task = task
        return cell
    }