user8105388
user8105388

Reputation:

UserDefaults in a UITableViewCell not saving (swift3)

My code right now just lists things you manually enter. However when the user switches view controllers the code disappears. I tried to use userdefualts to save my current code in the number of rows in selection function but it does not save the items in the tableview cells. I just want to save whatever is in the tableview cells.

import UIKit

class ViewController: UIViewController, UITableViewDataSource {

var items: [String] = [""]


@IBOutlet weak var listTableView: UITableView!
@IBAction func addItem(_ sender: AnyObject) {
    alert()
}

@IBOutlet weak var webView: UIWebView!

override func viewDidLoad() {
    super.viewDidLoad()
    listTableView.dataSource = self



}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "listitem") as! ItemTableViewCell
    cell.itemLabel.text = items[indexPath.row]

    cell.preservesSuperviewLayoutMargins = false
    cell.separatorInset = UIEdgeInsets.zero
    cell.layoutMargins = UIEdgeInsets.zero




    return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let userDefaults = UserDefaults.standard

    userDefaults.setValue(items, forKey: "items")
    userDefaults.synchronize()
    return items.count



}
func alert(){
    let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)
    alert.addTextField{
        (textfield) in
        textfield.placeholder = " Enter "

    }
    let add = UIAlertAction(title: "Add", style: .default){
        (action) in
        let textfield = alert.textFields![0] 

        self.items.append(textfield.text!)

        self.listTableView.reloadData()
    }
    let cancel = UIAlertAction(title: "Cancel", style: .cancel) {
        (alert) in


    }
    alert.addAction(add)
    alert.addAction(cancel)

    present(alert, animated: true, completion: nil)

}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    items.remove(at: indexPath.row)
    tableView.deleteRows(at: [indexPath], with: .automatic)


}}

Upvotes: 0

Views: 390

Answers (1)

Paulw11
Paulw11

Reputation: 114875

You have a number of issues in your code:

  1. You never load your data back from UserDefaults. - This is the big one
  2. There is no need to call synchronise.
  3. You should save your data when data is added/deleted, not in numberOfRowsInSection.
  4. It will look nicer if you insert a new row rather than reloading the whole table

I would suggest something like:

import UIKit

class ViewController: UIViewController, UITableViewDataSource {

    var items = [String]()

    @IBOutlet weak var listTableView: UITableView!
    @IBAction func addItem(_ sender: AnyObject) {
        alert()
    }

    @IBOutlet weak var webView: UIWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        listTableView.dataSource = self

        self.items = UserDefaults.standard.stringArray(forKey:"items")  ?? [String]()
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "listitem") as! ItemTableViewCell
        cell.itemLabel.text = items[indexPath.row]

        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsets.zero
        cell.layoutMargins = UIEdgeInsets.zero

        return cell
    }

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

    func saveData() {
        userDefaults.standard.set(items, forKey: "items")
    }

    func alert(){
        let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)
        alert.addTextField{
            (textfield) in
            textfield.placeholder = " Enter "

        }
        let add = UIAlertAction(title: "Add", style: .default){
            (action) in
            guard let textfield = alert.textFields?.first else {
                return
            }

            if let newText= textfield.text {
                self.items.append(newText)
                saveData()
                let indexPath = IndexPath(row: items.count - 1, section: 0)
                self.listTableView.insertRows(at: [indexPath], with: .automatic)
            }
        }

        let cancel = UIAlertAction(title: "Cancel", style: .cancel) {
            (alert) in

        }

        alert.addAction(add)
        alert.addAction(cancel)

        present(alert, animated: true, completion: nil)

    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        items.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .automatic)
        saveData()

    }
}

Also, you shouldn't really use UserDefaults for data storage this way, but I presume this is just a simple learning exercise.

Upvotes: 1

Related Questions