Just for completeness I’d like to show in this post how to make structs serializable in the same manner as enums (see this post). Again, we transform the struct to a dictionary of NSCoding compliant types and give it to an NSCoder (e.g. NSKeyedArchiver) for coding. The other way round we get the decoded dictionary and initialize the desired struct with it. Sounds simple, doesn’t it. Let’s start.
As for enums we have to implement the protocol „PropertyListReadable“ for our struct. As a reminder here is the protocol definition:
| 
					 1 2 3 4 5 6  | 
						typealias PropertyList = [String : Any] protocol PropertyListReadable {         // this protocol can be applied to any struct or enum     func propertyListRepresentation() -> PropertyList     init?(propertyListRepresentation:PropertyList?) }  | 
					
As an example let’s create a struct „Person“ that contains a name, an age and the mood of a person. The mood should be represented by the enum „Happiness2“ from my previous posts. So you can see that this mechanism can be nested as well.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33  | 
						struct Person: PropertyListReadable {     let name: String     var age: Int     var mood: Happiness2     init(withName name: String, andAge age: Int, andMood mood: Happiness2) {         self.name = name         self.age = age         self.mood = mood     }     init?(propertyListRepresentation: PropertyList?) {         guard let values = propertyListRepresentation else {return nil} // did we really get a dictionary?         if let name = values["name"] as? String {   // decode all properties             self.name = name         } else {return nil}         if let age = values["age"] as? Int {             self.age = age         } else {return nil}         if let pMood = values["mood"] as? PropertyList, // the decoded enum in its dictionary form             let mood = Happiness2(propertyListRepresentation: pMood) {  // transform it to the enum             self.mood = mood         } else {return nil}     }     func propertyListRepresentation() -> PropertyList {         var representation: PropertyList = [:]  // this will be the resulting dictionary         representation["name"] = name           // map all properties to dictionary entries         representation["age"] = age             // the enum is coded in its dictionary form         representation["mood"] = mood.propertyListRepresentation()         return representation     } }  | 
					
Let’s look at the encoding part first (lines 26 – 32). Here we have to transform the struct to a dictionary of NSCoding compliant types. Every property will be an entry in the dictionary with an identifying key (String) and its value. For the name (String) and the age (Int) that’s simple. The mood is an enum and its value is not NSCoding compliant by itself. But since we have made „Happiness2“ PropertyListReadable we can put its perpertyListRepresentation into the dictionary.
For the init part (lines 12 – 24) we make it the other way round. First we have to check that we’ve really got a dictionary for initializing the struct. Then we pick one by one the properties from the dictionary and fill the struct. For the property mood we do not get the enum itself from the dictionary but its propertyListRepresentation. From that we can initialize the enum mood. That’s it.
Let’s make a check and create an instance of our struct, encode it and decode it finally.
| 
					 1 2 3 4 5 6 7  | 
						let me = Person(withName: "Frank-Peter", andAge: 60, andMood: Happiness2.Happy(ofGrade: 5)) let data = NSKeyedArchiver.archivedData(withRootObject: me.propertyListRepresentation()) if let person = Person(propertyListRepresentation:     NSKeyedUnarchiver.unarchiveObject(with: data) as? PropertyList) {     Swift.print("person: \(person)") }  | 
					
Everything works fine. The decoded object is equal to the original one. Here is the playground of this example: