Search code examples
iosswiftnsuserdefaults

Delete not working and last value not display, User default with tableview


I implemented to save data in local using user dafaults with table view. when insert data every data display in my tableview. but stop and run again last value is not dispayed. and when swipe and remove not working when app run next time.

import UIKit
let defaults = UserDefaults(suiteName: "com.saving.data")

class HomeWorkViewController: UITableViewController {

    var rows = [String]()

call getData() method in viewDidload

    override func viewDidLoad() {
        super.viewDidLoad()
        getData()
        // Do any additional setup after loading the view.
        self.navigationItem.rightBarButtonItem = self.editButtonItem
    }

calling getData() method

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        getData()
    }

calling storeData method

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(true)
        storeData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func addButton(_ sender: Any) {
        addCell()
    }
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return rows.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "homeWork", for: indexPath)
        cell.textLabel?.text = rows[indexPath.row]
        return cell
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            rows.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
            tableView.reloadData()
        }else if editingStyle == .insert {

        }
    }

    func addCell(){
        let alert = UIAlertController(title: "Add Home Work", message: "Input text", preferredStyle: .alert)
        alert.addTextField{(textField) in
    textField.placeholder = "text...."
        }
        alert.addAction(UIAlertAction(title: "Confirm", style: .default, handler: {[weak alert](_) in
            let row = alert?.textFields![0]
            self.rows.append((row?.text)!)
            self.tableView.reloadData()
        }))
        self.present(alert,animated: true, completion: nil)
        storeData()
    }

    func storeData(){
        defaults?.set(rows, forKey: "savedData")
        defaults?.synchronize()
    }


    func getData(){
     let data = defaults?.value(forKey: "savedData")
        if data != nil {
            rows = data as! [String]
        }else{}
    }
}

Solution

  • You call storeData() at the wrong place. The addAction closure is executed later in time.

    func addCell() {
        let alert = UIAlertController(title: "Add Home Work", message: "Input text", preferredStyle: .alert)
        alert.addTextField{(textField) in
            textField.placeholder = "text...."
        }
        alert.addAction(UIAlertAction(title: "Confirm", style: .default, handler: {[weak alert](_) in
            let row = alert?.textFields![0]
            let insertionIndex = self.rows.count
            self.rows.append(row.text!)
            self.tableView.insertRows(at: IndexPath(row: insertionIndex, section: 0), with: .automatic)
            self.storeData()
        }))
        self.present(alert,animated: true, completion: nil)
    }
    

    And never call reloadData after calling deleteRows

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            rows.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
            self.storeData()
        }
    }
    

    And use the dedicated API of UserDefaults (don't call synchronize)

    func storeData(){
        defaults!.set(rows, forKey: "savedData")
    }
    
    
    func getData(){
        rows = defaults!.array(forKey: "savedData") as? [String] ?? []
    }