Wouter
Wouter

Reputation: 807

Saving a object in UserDefaults after reorder of rows in TableView

I search already a few days to the answer on the question how can I save a object after reorder the TableView with Swift? I found many tutorials on the internet show how to reorder and how to save it with a array.

Whatever I try I do not get out. I extract my data from entities. but when I try to save the sorted in userdefaults I get the following error:

[User Defaults] Attempt to set a non-property-list object

I can not figure out why i do not get the reorder stored.

This is my code right now. What do I wrong?
Please can you help me to the solution? Thank you very much.


import UIKit
import CoreData

class hondenTableViewController: UITableViewController {

    var honden = [Hond]() // legen array aanmaken
    var dateFormatter = DateFormatter()

    let store = UserDefaults(suiteName: "MultiSelectTable")
    var opgeslagenHonden = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        if let defaults = self.store?.array(forKey: "hondjes")  {
            self. opgeslagenHonden = defaults
        } 


        self.navigationItem.leftBarButtonItem = self.editButtonItem

        // Nederlands opgebouwde datum op geven
        dateFormatter.dateFormat = "E d MMM y"
        self.tableView.reloadData()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext

        let fetchReqeust = Hond.fetchRequest() as NSFetchRequest
        do {
            honden = try context.fetch(fetchReqeust)
        } catch let error {
            print("Ophalen mislukt door error\(error)")
        }

        tableView.reloadData()

    }
    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return honden.count

    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "hondenCellIdentifier", for: indexPath)
        let hond = honden[indexPath.row]

        cell.textLabel?.text = hond.naam

        if let date = hond.geboortedatum as Date? {
            let formatter = DateFormatter()
            formatter.dateFormat = "dd/MM/yyyy"

            cell.detailTextLabel?.text = "Geboren op : " + dateFormatter.string(from: date) + " = " + helper.berekenLeeftijd(formatter.string(from: date) + " oud.")

        } else {
            cell.detailTextLabel?.text = "Geboortedatum onbekend."
        }

        return cell
    }

    // Override to support conditional editing of the table view.
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }

    // Override to support editing the table view.
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

        if honden.count > indexPath.row {

            let hond = honden[indexPath.row]

            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let context = appDelegate.persistentContainer.viewContext

            context.delete(hond)
            honden.remove(at: indexPath.row)

            do {
                try context.save()
            } catch let error {
                print("Kan niet verwijderen door: \(error).")
            }

            tableView.deleteRows(at: [indexPath], with: .fade)
        }
    }

    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let movedObject = self.honden[sourceIndexPath.row]
        honden.remove(at: sourceIndexPath.row)
        honden.insert(movedObject, at: destinationIndexPath.row)

        let defaults = UserDefaults.standard
        defaults.set(honden, forKey: "hondjes")
        defaults.synchronize()
        //NSLog("%@", "\(sourceIndexPath.row) => \(destinationIndexPath.row) \(honden)")
    }

    // Override to support conditional rearranging of the table view.
    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the item to be re-orderable.
        return true
    }

}

I will be glad for help :)

Upvotes: 0

Views: 214

Answers (2)

Duncan C
Duncan C

Reputation: 131426

As @donnywals says in his answer, you can't write custom objects directly to UserDefaults. Only a small list of data types (the ones I can remember are Date, Array, Dictionary, Int, Float, Double, Data, String.) called "property list objects" can be written to UserDefaults, or to a property list file.

It looks to me like you're using Core Data, so why are you trying to write your array of objects to UserDefaults? It's a mis-use of UserDefaults, and it's what CoreData is designed to do, so why not save your data into Core Data?

Upvotes: 1

donnywals
donnywals

Reputation: 7591

You can't write an object of type [Hond] to UserDefaults. One option you have is to make Hond conform to Codable and encode your array into Data using JSONEncoder before you write it and decode data into [Hond] when you retrieve it:

let encoder = JSONEncoder()
let data = try? encoder.encode(honden)
defaults.set(data, forKey: "hondjes")

// and

let loadedData = defaults.data(forKey: "hondjes")!
let decoder = JSONDecoder()
let honden = try? decoder.decode([Hond].self, from: loadedData)

Also, check the docs for synchronize, you shouldn't call that manually in your code :)

Upvotes: 1

Related Questions