Reputation: 245
I am wondering how to let my to-do-list be the same after the app is closed. In my code I am declaring an array right in the beginning and I want to know how I can save it updated for the user, after he restarted the App. I searched the web for some answers but only found old ideas about creating entities in storyboard. And I am pretty sure, that by now there has to be something more beautifully than adding it manually.
How can I save the array when it is getting updated, so it won't get lost after an app restart?
My Code:
import UIKit
var checklist = ["Item 1", "Item 2"]
class ChecklistViewController: BaseViewController, UITableViewDelegate, UITableViewDataSource{
var newChecklistItemString: String?
var alertInputTextField: UITextField?
@IBOutlet weak var myTableView: UITableView!
let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var selectedChecklist: [String] = []
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (checklist.count)
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 18.0)
cell.textLabel?.text = checklist[indexPath.row]
if selectedChecklist.contains(checklist[indexPath.row]) {
cell.accessoryType = .checkmark
}
else{
cell.accessoryType = .none
}
return cell
}
// checkmarks when tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
selectedChecklist.append(checklist[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let value = checklist.remove(at: indexPath.row)
myTableView.reloadData()
}
}
override func viewDidAppear(_ animated: Bool) {
myTableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func addNewObject(_ sender: Any) {
let alert = UIAlertController(title: "New Item", message: nil, preferredStyle: .alert)
alert.addTextField { (alertInputTextField) in
alertInputTextField.autocapitalizationType = .sentences
}
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
self.dismiss(animated: true, completion: nil)
}))
alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { (action) in
let textf = alert.textFields![0] as UITextField
if(textf.text != "")
{
checklist.append(textf.text!)
}
self.myTableView.reloadData()
}))
self.present(alert, animated: true, completion: nil)
}
}
Upvotes: 1
Views: 391
Reputation: 285039
For a simple string array use UserDefaults
Declare two methods to load and save data
func loadDefaults()
{
self.checklist = UserDefaults.standard.array(forKey: "checklist") as? [String] ?? []
}
func saveDefaults()
{
UserDefaults.standard.set(self.checklist, forKey: "checklist")
}
In viewDidLoad
add
loadDefaults()
And right after adding and removing an item add
saveDefaults()
For more complex data other solutions like Core Data are preferable
Note:
Rather than always reloading the entire table view use the API to insert and delete single rows. The benefit is a nice animation.
In tableView:commit
replace myTableView.reloadData()
with
myTableView.deleteRows(at: [indexPath], with: .automatic)
and in the alert action replace the entire if
expression with
if !textf.text!.isEmpty {
let indexPath = IndexPath(row: checklist.count, section: 0)
checklist.append(textf.text!)
myTableView.insertRows(at: [indexPath], with: .automatic)
}
And move the variable checklist
into the class!
Upvotes: 2
Reputation: 714
Check the code below:-
class ClassUserDefaults {
static let shared = ClassUserDefaults()
// MARK: - SETTER GETTER
var selectedChecklist: [String]? {
get {
guard let savedItem = (UserDefaults.standard.object(forKey: "selectedChecklist")) as? Data else { return nil }
guard let data = NSKeyedUnarchiver.unarchiveObject(with: savedItem) as? [String]? else { return nil}
return data
}
set {
guard let value = newValue else {
UserDefaults.standard.removeObject(forKey: "selectedChecklist")
return
}
let item = NSKeyedArchiver.archivedData(withRootObject: value)
UserDefaults.standard.set(item, forKey: "selectedChecklist")
UserDefaults.standard.synchronize()
}
}
}
usage in your ViewController:-
ClassUserDefaults.shared.selectedChecklist = selectedChecklist
also you want to set wherever you want like:-
cell.textLabel?.text = ClassUserDefaults.shared.selectedChecklist[indexPath.row]
Hope it helps :)
Upvotes: 1
Reputation: 2142
Find this solution:
// Use this code to fetch saved item list.
if let items = UserDefaults.standard.value(forKey: "ItemListArray") as? [String] {
print(items)
}
// Use this code to save your item list.
let itemList = ["Item 1", "Item 2", "Item 3", "Item 4"]
UserDefaults.standard.setValue(itemList, forKey: "ItemListArray")
// Use this code to remove item list
UserDefaults.standard.setValue(nil, forKey: "ItemListArray")
Upvotes: 1