Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save an Array with Objects to UserDefaults

My Object conforms to the new Swift 4 Codeable protocol. How to save an array of these Objects in UserDefaults?

struct MyObject: Codeable {
    var name: String
    var something: [String]
}

myObjectsArray = [MyObject]() // filled with objects
UserDefaults.standard.set(myObjectsArray, forKey: "user_filters")

Error

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object

like image 410
Jan Avatar asked Jul 12 '17 12:07

Jan


People also ask

How do you save an array of objects in UserDefaults?

Let's take a look at an example. We access the shared defaults object through the standard class property of the UserDefaults class. We then create an array of strings and store the array in the user's defaults database by invoking the set(_:forKey:) method of the UserDefaults database.

How can you store object to UserDefaults?

To store them in UserDefaults, we need to implement or confirm Codable to the user-defined class or struct. Codable is a typealias of Decodable & Encodable protocols. It adds the functionality of Encoding and Decoding to the class or struct.

Can we store custom object in UserDefaults?

UserDefaults can simply save custom object which conforms to Codable protocol. JSONEncoder and JSONDecoder play important roles for handling the data transformation. Nested object must also conform to Codable protocol in order to encode and decode successfully.

How data is stored in UserDefaults?

Writing or Setting Values To User Defaults You simply invoke the set(_:forKey:) method on the UserDefaults instance. In this example, we set the value of myKey to true by invoking the set(_:forKey:) method on the shared defaults object.


1 Answers

Whew, I got it working:

Here is the Swift 4 Syntax to save an Array with Codeable Objects:

My solution is to encode it as a JSON Object and save that:

static var getAllObjects: [MyObject] {
      let defaultObject = MyObject(name: "My Object Name")
      if let objects = UserDefaults.standard.value(forKey: "user_objects") as? Data {
         let decoder = JSONDecoder()
         if let objectsDecoded = try? decoder.decode(Array.self, from: objects) as [MyObject] {
            return objectsDecoded
         } else {
            return [defaultObject]
         }
      } else {
         return [defaultObject]
      }
   }

 static func saveAllObjects(allObjects: [MyObject]) {
      let encoder = JSONEncoder()
      if let encoded = try? encoder.encode(allObjects){
         UserDefaults.standard.set(encoded, forKey: "user_objects")
      }
 }
like image 73
Jan Avatar answered Dec 10 '22 21:12

Jan