I am trying to save and retrieve tableViewCell checkmark using NSUserDefaults.My partial code as below.From the code,I can able to select or deselect cell using UITableViewC
First of all create a class Item
as data source with a name
and selected
property.
class Item {
let name : String
var selected = false
init(name: String) {
self.name = name
}
}
Declare the data source array
var myItems = [Item]()
Create the items this way
let item = Item(name:"Foo") // your former string value, `selected` is false by default.
myItems.append(item)
In applicationDidFinishLaunching
register an empty string array as default value for key selectedCells
let defaults = NSUserDefaults.standardUserDefaults()
let defaultValues = ["selectedCells" : [String]()]
defaults.registerDefaults(defaultValues)
To read all selected cells from user defaults get the string array and set the property selected
of all corresponding items to true. Then reload the table view. The forced unwrapping is safe because the key/value is pre-registered and always non-optional. Important: Make sure that readDefaults()
is always called after registering the default values.
func readDefaults()
{
let defaults = NSUserDefaults.standardUserDefaults()
let selectedItems = defaults.stringArrayForKey("selectedCells")!
for item in myItems {
item.selected = selectedItems.contains(item.name)
}
tableView.reloadData()
}
In cellForRowAtIndexPath
set both properties accordingly
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
let item = myItems[indexPath.row]
cell.textLabel!.text = item.name
cell.accessoryType = item.selected ? .Checkmark : .None
cell.selectionStyle = .None
cell.tintColor = UIColor.greenColor()
return cell
}
To save the data filter all items whose selected
property is true, map it to the names and save the array.
func saveDefaults() {
let selectedCells = myItems.filter { $0.selected }.map { $0.name }
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(selectedCells, forKey:"selectedCells")
}
Now you should change the model in didSelectRowAtIndexPath
and reload the row. This is much more efficient (and recommended) than manipulating the cell
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let item = myItems[indexPath.row]
item.selected = true
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
My example, i Load in tableView set in DetailController
Model ----
struct TheoryData {
var id: String
var theoryText: String
var theoryModes: String
var theoryImage: String
var like: Bool
}
Read values
var theoryData = [TheoryData]()
private func readDefaults() {
let defaults = UserDefaults.standard
let selectedItems = defaults.stringArray(forKey: "selectedCells") ?? []
(0..<theoryData.count).forEach { i in
theoryData[i].like = selectedItems.contains(theoryData[i].id)
}
menuTableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
readDefaults()
}
In cell
let theory = theoryData[indexPath.row]
cell.likeImage.image = theory.like ? #imageLiteral(resourceName: "heart-icon") : #imageLiteral(resourceName: "heart-empty-icon")
Save state in UserDefault
@IBAction func likeButtonTapped(_ sender: UIButton) {
theoryData.like.toggle()
let likeIcon = theoryData.like ? #imageLiteral(resourceName: "heart-icon") : #imageLiteral(resourceName: "heart-empty-icon")
likeButton.setImage(likeIcon, for: .normal)
saveSelection()
}
private func saveSelection() {
let defaults = UserDefaults.standard
var selectedItems = defaults.stringArray(forKey: "selectedCell") ?? []
if theoryData.like {
selectedItems.append(theoryData.id)
} else {
selectedItems = selectedItems.filter{ $0 != theoryData.id }
}
print(selectedItems)
defaults.setValue(selectedItems, forKey: "selectedCell")
}
}