I am fairly new to Swift and I am having an issue on TableView multi-selection. I have multiple selections that I can check with a checkmark, similar to to-do list.
When I check the items I want to be able to come back to the ListView and have my selections saved. I'm assuming that the code to keep this in saved state would go somewhere here? This is the class where the individual cell item checkmark is written :
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 go about this?
This is the 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)
}
Two things:
Your code in cellForRowAtIndexPath:
is perfect. It takes the info from listItems[indexPath.row]
to populate your cell's text and checkmark. But in your didSelectRowAtIndexPath:
, you never change listItems
such that cellForRowAtIndexPath:
has the updated data from which to pull the new row upon reload. So instead of using deselectRowAtIndexPath:
, simply update the listItems
array then reloadRowsAtIndexPaths
. (Honestly, I'm confused as to why it was working for you up to this point since you were calling reload on un-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)
}
Secondly, as long as that array is being stored in a view controller that's not being deallocated, you won't lose that data and you'll be able to repopulate the table. But if it's being stored in a view controller (or table view controller) that's being deallocated, you may want to store it elsewhere in your program.
I presume you have an array of ListItem representing the model data (the contents of the table view). Then to preserve this outside the running app you can save it off into NSUserDefaults or into a file. To do so, you will need a way of serializing a ListItem. The usual way to do this is to have ListItem adopt the NSCoding protocol and implement encodeWithCoder:
and init(coder:)
to use NSKeyedArchiver and NSKeyedUnarchiver (the "coder" in those methods) to turn a ListItem object into an NSData and vice versa. Once you've done that, an array of ListItem can be directly serialized with NSKeyedArchiver and NSKeyedUnarchiver.
Solved this mixing and matching a bit, using NSUserDefaults Here it goes:
Created a button in the navigation bar of my pop-over Table/ListView and functionalities to the button:
//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 for loading the initial data array, which holds my list items, created a variable savedValues which looked 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 naturally, don't forget to call loadInitialData()
in your viewDidLoad()
Thank you to all that helped me out :)
来源:https://stackoverflow.com/questions/27237326/swift-save-checkmarks-selected-in-tableview