neda Derakhshesh
neda Derakhshesh

Reputation: 1163

how to save changes after reordering data in edit mode

I am completely new to swift developing. I want to implement a UI table view which it could shows a list of my items in array like the image below

how my table views

It works fine but when I move items places and then I touch done button, after restart the app, every changes that I have made, resets to its default. I searched a lot and I found that I should save it on user defaults. I read lots of articles but still I do not know what should I do with codes, I appreciate if some one could edit my codes the way I need (reordering changes could save on device and not refreshing each time I open the app)

here is my codes in viewController

   //  ViewController.swift
  //  Created by Sebastian Hette on 28.02.2017.

import UIKit

  class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var array = ["one", "two", "three", "four", "five"]

let defaults = UserDefaults.standard
//I defined user defaults here

 struct Constants {

    static let myKey = "myKey"
}
//I defined my static key here

@IBOutlet weak var myTableView: UITableView!
@IBOutlet weak var editButton: UIBarButtonItem!

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{


    let cell = tableView.dequeueReusableCell(withIdentifier: "cell")

    defaults.stringArray(forKey: Constants.myKey)
    //I retrieve user defaults here 


    cell?.textLabel?.text = array[indexPath.row]
    return cell!
}

//Allows reordering of cells
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool
{
    return true
}

func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
{
    let item = array[sourceIndexPath.row]
    array.remove(at: sourceIndexPath.row)
    array.insert(item, at: destinationIndexPath.row)
}


@IBAction func edit(_ sender: Any)
{
    myTableView.isEditing = !myTableView.isEditing

    switch myTableView.isEditing {
    case true:
        editButton.title = "done"
    case false:
        editButton.title = "edit"
    }



    defaults.set(array, forKey: Constants.myKey)
    //I saved my user defaults here 
}


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


   }

Upvotes: 1

Views: 670

Answers (1)

CodeNinja
CodeNinja

Reputation: 626

First you'll need a UserDefaults object:

let defaults = UserDefaults.standard

To save:

defaults.set(0, forKey: "myNumber")
defaults.set("hello", forKey: "myString")
defaults.set(["apple", "banana", "grape"], forKey: "myArray")

To retrieve:

defaults.integer(forKey: "myNumber")
defaults.string(forKey: "myString")
defaults.stringArray(forKey: "myArray") // you can also save any type of array by using defaults.array

You can save multiple types, including numbers (int, double, float, etc), strings, boolean, object, and arrays. I recommend storing the keys in a separate Constants or similar file, because typos in the key values could cause this not to work and you'll be banging your head on the wall trying to figure out a more complex reason as to why your app isn't working. An example:

static let myKey = "myKey"

and to use would be

Constants.myKey

By using UserDefaults your app will save the order of your data even after it closes. Instead of declaring an array in your ViewController, initialize your array in viewDidLoad.

EDIT:

You're almost there. I'm not seeing a viewDidLoad method, which I believe you'll need. Here's a little sample I whipped up:

class ViewController: UIViewController {

    var array = [String]() // declaring a String array
    let defaults = UserDefaults.standard // where the data will be stored

    override func viewDidLoad() {
        super.viewDidLoad()

        // this sets the array equal to the last saved array, or the default one if one has not been saved
        array = defaults.stringArray(forKey: myKey) ?? ["one", "two", "three", "four", "five"]
    }
}

Every time you are ready to save your new ordered array call defaults.set(array, forKey: myKey). In your cellForRowAtIndexPath method, take out the line where you retrieve user defaults, you won't need it now that you're retrieving it on viewDidLoad and setting it equal to your array variable.

And if it were me, I would save the user defaults as the last line in the moveRowAt method.

Upvotes: 2

Related Questions