fs_tigre fs_tigre - 2 months ago 20
Swift Question

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
NSUserDefaults
and 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

Answer

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

if editingStyle == UITableViewCellEditingStyle.Delete {
    array.removeAtIndex(indexPath.row)
    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    let userDefaults = NSUserDefaults.standardUserDefaults()
    userDefaults.setObject(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.dequeueReusableCellWithIdentifier("Cell", forIndexPath: 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 = NSUserDefaults.standardUserDefaults()
    guard let data = userDefaults.objectForKey("myArrayKey") as? [String] else {
        return 
    }
    array = data
    tableView.reloadData()
}   
Comments