Checkbox in UITableView not working when row is de

2019-09-19 10:22发布

问题:

I have implemented a checkbox in UITableView controller, it works perfectly but when the checkbox are selected and the rows in the tableview are deleted and the when I add a new row to the tableview it gets selected. Here is a link to my project: https://files.fm/f/tepkz2du I think it has something to do with when a row is delete, the index path is messed up.

UPDATED CODE:

cellForRowAt:

if let btnChk3 = cell?.contentView.viewWithTag(100) as? UIButton {
            btnChk3.addTarget(self, action: #selector(checkboxClicked(_ :)), for: .touchUpInside)
        }

if let btnChk2 = cell.contentView.viewWithTag(22) as? UIButton {
        btnChk2.isSelected = UserDefaults.standard.integer(forKey: myarray[indexPath.row]) == (indexPath.row + index) ? true : false
    }

checkboxClicked

    let defaults = UserDefaults.standard
    let myarray = defaults.stringArray(forKey: "ScheduleArray") ?? [String]()
    if  sender.tag == 100 {

        if let btnChk2 = cell.contentView.viewWithTag(22) as? UIButton {
            if btnChk2.isSelected == true {
                btnChk2.isSelected = false
                UserDefaults.standard.set(-1, forKey: myarray[(indexPath?.row)!] )
                UserDefaults.standard.synchronize()

            }else{
                btnChk2.isSelected = true
                UserDefaults.standard.set((indexPath?.row)! + index, forKey: myarray[(indexPath?.row)!])
                UserDefaults.standard.synchronize()
            }
        }
        sender.isSelected = false
    }

editingStyle == .delete:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {

    if tableView == ScheduleTableView{


        let defaults = UserDefaults.standard
        var myarray = defaults.stringArray(forKey: "ScheduleArray") ?? [String]()
        print(myarray)
        myarray.remove(at: indexPath.row)
        defaults.set(myarray, forKey: "ScheduleArray")
        ScheduleTableView.deleteRows(at: [indexPath], with: .fade)


    }
 }

回答1:

Don't save index path in UserDefaults , save any value which you are showing in table cell. And match it with array in cellForRowAtIndex . like I did

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let c = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! tabCell
    c.lblC.text = arry?[indexPath.row]
    /* for example
     arry = ["First","Second","Third","Fourth","Fifth","Sixth","Seventh","eight","Ninth","Tenth"]
    seleted = ["First","Fifth"]
    */
    print("indexpath--",indexPath.row)
    if selected != nil
    {
        if (selected?.contains((arry?[indexPath.row])!))!
        {
            c.btnCheck.setBackgroundImage(#imageLiteral(resourceName: "check.png"), for: .normal)
        }
        else
        {
            c.btnCheck.setBackgroundImage(#imageLiteral(resourceName: "uncheck.png"), for: .normal)
        }


    }
    c.btnCheck.tag = indexPath.row
    c.btnCheck.addTarget(self, action:#selector(btnCheckClick(btn:)) , for: .touchUpInside)
    return c
}

I am not able to run your code ... thats way I made my demo check it, hope you can get an idea... https://files.fm/u/hj7jz9dj



回答2:

if let btnChk2 = cell.contentView.viewWithTag(22) as? UIButton {
            btnChk2.isSelected = UserDefaults.standard.integer(forKey: myarray[indexPath.row]) == (indexPath.row + index) ? true : false
        }

CHANGE IN cellForRowAt

 let defaults = UserDefaults.standard
        let myarray = defaults.stringArray(forKey: "ScheduleArray") ?? [String]()
if  sender.tag == 100 {

            if let btnChk2 = cell.contentView.viewWithTag(22) as? UIButton {
                if btnChk2.isSelected == true {
                    btnChk2.isSelected = false
                    UserDefaults.standard.set(-1, forKey: myarray[(indexPath?.row)!] )
                    UserDefaults.standard.synchronize()

                }else{
                    btnChk2.isSelected = true
                    UserDefaults.standard.set((indexPath?.row)! + index, forKey: myarray[(indexPath?.row)!])
                    UserDefaults.standard.synchronize()
                }
            }
            sender.isSelected = false
        }

CHANGE IN checkboxClicked



回答3:

You could use func prepareForReuse() method in the UITableViewCell to make sure the checkbox is unselected when you insert a new row.



回答4:

You store in userdefaults the value of the checked button according to its indexpath. The problem with this attitude is when you delete the cell, the new cell is getting the indexpath of the previous cell which is wrong.

You should work with a model to represent your rows. Store in the "ScheduleArray" an object instead of just a string.

Something like that:

struct myRow {
    var title: String = ""
    var isSelected: Bool = false
}