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)
}
source to share
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.
source to share
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.
source to share
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 :)
source to share