0
import UIKit

struct Task {
    var name: String
    var completed: Bool
}

class ListModel {

    var tasks: [Task] = [] // array to store tasks of todo list

    let defaluts = UserDefaults.standard

    func addTask( name: String, completed: Bool ) {   // store task with status of complete into array
        self.tasks.append( Task( name: name, completed: completed ) )
    }

    var tasksValue: [Task] { // getter and setter of array tasks
        get {
            return tasks
        }
        set {
            tasks = newValue
        }
    }

    func save() {
        defaluts.set(tasks, forKey: "tasks")
    }

    func load() {
        if let value = defaluts.array(forKey: "tasks") as? [Task] {
            tasks = value 
        }
    }
}

When I run my program, it displays error that Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object.

Can someone help me fix it please?

Bo L
  • 21
  • 7

1 Answers1

0

The answer is simple. You can only save a small list of data types (property list types: Array, Dictionary, String, Data, Date, Int, Double, Float, Bool) to either UserDefaults or a property list.

If you try to write any other object type, or a container that contains any other type, it fails. You will need to serialize your custom object to some other type.

Also, you're not to store anything but small user setting values to Defaults.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thank you for your suggestion, so I could split the array into two types right? I mean, type of array is Task, which is struct, but I could only use String and Bool in struct with UserDefaults right? – Bo L Mar 10 '18 at 12:10
  • Probably the best solution is to have your custom object conform to NSCoding, and then you can save the entire array of objects to a property list directly. – Duncan C Mar 10 '18 at 12:12
  • Thank you, I'll try to fix it – Bo L Mar 10 '18 at 12:17
  • Note that if you're using Swift 4 (which you should be for new development) you can have your objects conform to the Coding protocol and then use either JSONEncoder/JSONDecoder (to encode/decode JSON) or PropertyListEncoder/PropertyListDecoder (to encode/decode as a property list.) – Duncan C Mar 10 '18 at 15:25
  • If all of your object's properties are simple types, or custom types who's properties are simple types, you can use the new Coding protocol to serialize/deserialize your objects with **no** custom code. – Duncan C Mar 10 '18 at 15:27
  • Thank you, I fixed it out already, and everything looks great so far – Bo L Mar 11 '18 at 02:46