fs_tigre
fs_tigre

Reputation: 10738

The proper way to delete rows from UITableView and update array from NSUserDefaults in Swift / iOS

What is the proper way to delete rows from UITableView and update array from NSUserDefaults?

In the following example I'm reading an array from NSUserDefaultsand feeding a UITableView with its content, I'm also allowing the user to delete items in the UITableView what I'm not sure is when to read and write to NSUserDefaults so the table updates as soon as a row is deleted. As you can see I start by reading the array the in the viewDidLoad method and re-saving it in the commitEditingStyle method. With this method my table is not reloading when a row is deleted.

override func viewDidLoad() {
    super.viewDidLoad()
     // Lets assume that an array already exists in NSUserdefaults.
     // Reading and filling array with content from NSUserDefaults.
    let userDefaults = NSUserDefaults.standardUserDefaults()
    var array:Array = userDefaults.objectForKey("myArrayKey") as? [String] ?? [String]()
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = UITableViewCell()
    cell.textLabel!.text = array[indexPath.row]
    return cell
}

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == UITableViewCellEditingStyle.Delete {
        array.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    }
  // Save array to update NSUserDefaults     
 let userDefaults = NSUserDefaults.standardUserDefaults()
 userDefaults.setObject(array, forKey: "myArrayKey")


 // Should I read from NSUserDefaults here right after saving and then reloadData()?
 }

How is this usually handled?

Thanks

Upvotes: 2

Views: 1208

Answers (1)

vadian
vadian

Reputation: 285079

Basically it's correct, but you should only save in user defaults if something has been deleted.

if editingStyle == .delete {
    array.remove(at: indexPath.row)
    tableView.deleteRows(at: [indexPath], with: .automatic)
    let userDefaults = UserDefaults.standard
    userDefaults.set(array, forKey: "myArrayKey")
}
  

Reading the array back is not needed and not recommended.

In cellForRowAtIndexPath reuse the cell, you need to specify the identifier in Interface Builder.

let cell = tableView.dequeueReusableCell(withIdentifier:"Cell", for: indexPath) 

The data source array must be declared on the top level of the class

var array = [String]()

then assign the value in viewDidLoad and reload the table view.

override func viewDidLoad() {
    super.viewDidLoad()

    let userDefaults = UserDefaults.standard
    guard let data = userDefaults.array(forKey: "myArrayKey") as? [String] else {
        return 
    }
    array = data
    tableView.reloadData()
}   

Upvotes: 3

Related Questions