Swift - keep checkboxes selected in TableView

I am new to Swift and I have a problem with multi-display TableView. I have several options that I can check with a check mark, similar to a to-do list.

When I check the items I want to go back to the ListView and save my settings. I'm guessing the code to keep this in a saved state would be around here somewhere? This is the class in which the label of the individual cell elements is marked:

    class ListItem: NSObject {
    let itemName: String
    var completed: Bool

    init(itemName: String, completed: Bool = false)
    {
        self.itemName = itemName
        self.completed = completed
    }
}   

      

Can someone please show me how to do this?

This is cellForRowAtIndexPath

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let tempCell = tableView.dequeueReusableCellWithIdentifier("ListPrototypeCell") as UITableViewCell
    let listItem = listItems[indexPath.row]

    // Downcast from UILabel? to UILabel
    let cell = tempCell.textLabel as UILabel!
    cell.text = listItem.itemName

    if (listItem.completed)
    {
        tempCell.accessoryType = UITableViewCellAccessoryType.Checkmark;
    }
    else
    {
        tempCell.accessoryType = UITableViewCellAccessoryType.None;
    }

    return tempCell
}    

      

and my didSelectRowAtIndexPath

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: false)

    let tappedItem = listItems[indexPath.row] as ListItem
    tappedItem.completed = !tappedItem.completed

    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)

}    

      

+3


source to share


3 answers


Two things:

Your code is cellForRowAtIndexPath:

perfect. It takes information from listItems[indexPath.row]

to fill in the text and checkmark of the honeycomb. But in yours didSelectRowAtIndexPath:

you never change listItems

, so it cellForRowAtIndexPath:

has updated data from which you can pull a new row out on reboot. So instead of using it, deselectRowAtIndexPath:

just update the array listItems

, then reloadRowsAtIndexPaths

. (To be honest, I'm confused as to why it worked for you up to this point, since you were causing a reboot on non-updated data.) Here's what I recommend:



override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let tappedItem = listItems[indexPath.row] as ListItem
    tappedItem.completed = !tappedItem.completed

    // Store the updated tappedItem back at the listItems index
    listItems[indexPath.row] = tappedItem

    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)

}

      

Second, as long as this array is stored in a view controller that is not freed, you will not lose this data and you can repopulate the table. But if it is stored in a view controller (or table view controller) that is being deallocated, you may want to store it elsewhere in your program.

+1


source


I am assuming you have a ListItem array representing the model data (table view content). Then, to keep this outside of the launching application, you can save it to NSUserDefaults or to a file. To do this, you need a way to serialize the ListItem. The usual way to do this is for the ListItem to adopt the NSCoding protocol and implement encodeWithCoder:

and init(coder:)

to use NSKeyedArchiver and NSKeyedUnarchiver (the "encoder" in these methods) to turn the ListItem into NSData and vice versa. Once you've done this, the ListItem array can be directly serialized using NSKeyedArchiver and NSKeyedUnarchiver.



0


source


Solved this mixing and bit mapping using NSUserDefaults Here it is:

Created a button in the navigation bar of my Table / ListView and button functionality:

 //create a done button in the navigation bar
    var done = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: Selector("doneBtn"))
    self.navigationItem.rightBarButtonItem = done

}

//This is the "Done" button functionality

func doneBtn()
{

    var saveString = ""

    for var i=0; i<listItems.count; i++
    {
        let listItem = listItems[i]
        if (listItem.completed)
        {
            saveString = saveString + "  " + "\(i)"
        }
    }

    saveString = saveString.stringByTrimmingCharactersInSet(NSCharacterSet .whitespaceAndNewlineCharacterSet())

    NSUserDefaults.standardUserDefaults().setValue(saveString, forKey: "savedValues")
    NSUserDefaults.standardUserDefaults().synchronize()


    self.navigationController?.dismissViewControllerAnimated(true, completion: nil)


    }

      

Then, in my func to load the original data array that contains my list items, I created a savedValues โ€‹โ€‹variable that looks like this:

 var savedValues : String? = NSUserDefaults.standardUserDefaults().valueForKey("savedValues") as? String



    if(!(savedValues==nil))
    {
        var nsStr: NSString = savedValues!
        let array = nsStr.componentsSeparatedByString("  ");
        for val in array {
            listItems[val.integerValue].completed = true
        }
    }

      

And of course, do not forget to call loadInitialData()

yourviewDidLoad()

Thanks everyone for helping me :)

0


source







All Articles