3

I'm trying to create an application to select/deselect rows in tableView, all data is loaded from coreData, and when I select an element that allows me to update it in coreData and vice versa,

at the beginning everything is OK, I load data from coreData, display all items in tableView and check rows if needed in cellForRowAtindexPath

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    var cell:UITableViewCell? = nil

    let item = (arrayToDisplay[indexPath.section] as Array<NSManagedObject>)[indexPath.row]

    cell = tableView.dequeueReusableCell(withIdentifier: "ShoppingCell")!

    let lblName:UILabel = cell?.viewWithTag(101) as! UILabel

    let attributedString = NSMutableAttributedString(string: (item.value(forKeyPath: "name") as! String?)!)

    if( item.value(forKeyPath: "bought") as! Bool)
    {
        attributedString.addAttribute(NSStrikethroughStyleAttributeName, value: NSNumber(value: NSUnderlineStyle.styleSingle.rawValue), range: NSMakeRange(0, attributedString.length))
        attributedString.addAttribute(NSStrikethroughColorAttributeName, value: UIColor.red, range: NSMakeRange(0, attributedString.length))

        cell?.setSelected(true, animated: true) //set checkMark to active/checked status

    }


    lblName.attributedText = attributedString

    return cell!
}

before that, I've enabled editingStyle like below

func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
    return UITableViewCellEditingStyle(rawValue: 3)!
}

Everything is working correctly when I load the view for the first time, when I check or uncheck I update value in CoreData and reload my tableView, I reload data from coreData and tableView in viewDidAppear, so whenever I switch between scenes there will be a refresh, using new data

When I check an item in my tableView, I save data, update my class array, and reloadData to display new changes (including text strikethrough)

and here is the issue, whenever I reload tableView, or switch between tabs (in TabBar), and Go back, checkmarks are not checked properly, and I'm not able to check them, they appear like they were checked and unchecked in less than a second,

I've checked maybe I have some conflicts in my code but everything is correct as all update operations to coreData are done properly,

I've followed sample project from Maitrayee Ghosh writen in ObjC, you can simulate the same problem by adding [tableView reloadData] to didSelectRowAtIndexPath like below

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"user selected %@",[dataArray objectAtIndex:indexPath.row]);

[tableView reloadData];}

So, How can I refresh tableView content with checkmarks status checked properly with the ability to change status, something like Google Keep checkbox notes

Godrix
  • 33
  • 3
  • What is your use of `UITableViewCellEditingStyle(rawValue: 3)`? Only use one of the valid values of `.none`, `.delete`, or `.insert`. Anything else is undocumented and could break in the future. – rmaddy Mar 10 '17 at 16:46
  • the `rawvalue: 3` is .checkmark available via `cell?.accessoryType = .checkmark` :/ – Godrix Mar 10 '17 at 16:58
  • That's completely wrong. If you want to set a checkmark, then set the proper accessory type. You can't use a completely unrelated value for the editing style. – rmaddy Mar 10 '17 at 17:00
  • @rmaddy I guess I have to change that editing style and maybe create my own checkbox or an external one, that will be safer... as it's not documented nor enumerated like `.none` `.delete` and `.insert` – Godrix Mar 10 '17 at 17:09

1 Answers1

2

Two things.

In cellForRowAt you need an else to your if statement.

if( item.value(forKeyPath: "bought") as! Bool)
{
    attributedString.addAttribute(NSStrikethroughStyleAttributeName, value: NSNumber(value: NSUnderlineStyle.styleSingle.rawValue), range: NSMakeRange(0, attributedString.length))
    attributedString.addAttribute(NSStrikethroughColorAttributeName, value: UIColor.red, range: NSMakeRange(0, attributedString.length))

    cell?.setSelected(true, animated: false)
} else {
    cell?.setSelected(false, animated: false)
}

Cells get reused so you must always handle both cases.

In your didSelectRowAt method you need to update your data model so that cellForRowAt renders the cell properly.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • thanks @rmaddy, I've tried it with `else` before and now, still same problem, also datamodel updated in both coreData and local object used to fill tableView, checked all data, the text strikethrough is working perfectly – Godrix Mar 10 '17 at 16:56
  • You need to make sure your data model is properly updated and persisted. – rmaddy Mar 10 '17 at 16:57
  • as I said just above in my first comment, all my data is checked and updated, that's strange – Godrix Mar 10 '17 at 17:01