11

I have a series of nested objects that I am needing to put through the NSCoding protocol so that I can save the top level object into NSUserDefaults.

Here is the structure of objects:

'Instructor' class

  • NSMutableArray that holds instances of...

'Class' class

  • NSMutableArray that holds instances of...

'Student' class

  • Name Property
  • Number Property
  • Money Property

I am needing to save an instance of Instructor to NSUserDefaults or to documents for the app. As you can see the Instructor object is holding an array that is then holding instances of a class. That class object is holding instances of students.

Is the NSCoding protocol recursive? What I mean by that is if I add the NSCoding protocol to each class, I could then save an Instructor object and it would recursively encode the contained objects?

Would it then work the same way while decoding? I could just decode the one instructor class and it would recursively decode the objects contained because they also conform to the NSCoding protocol?

How could I go about setting this up?

2
  • NSUserDefaults isn't an appropriate place to store that kind of user data. Why not just store it as a custom document in the Documents directory? Commented Sep 25, 2013 at 20:39
  • That's why I said I will save it to either NSUserDefaults or to documents. The reason I would consider NSUserDefaults is because the size of the instructor object would be very small. Commented Sep 25, 2013 at 22:08

2 Answers 2

18

Yes, you can (and probably should) write your support for NSCoding to be recursive. That's how NSCoding is supposed to work.

When your implement encodeWithCoder, simply call

[coder encodeObject: aProperty forKey: @"propertyName"];

on all your object's properties, including it's container properties.

Then make sure every object in your object's object graph also conforms to NSCoding.

For scalar properties, you can save the scalar value using NSCoder methods like encodeInt:forKey:

To save an object that conforms to NSCoding to user defaults, first convert it to NSData using the NSKeyedArchiver class method archivedDataWithRootObject, then save the resulting data into defaults. Quite simple, really.

Sign up to request clarification or add additional context in comments.

4 Comments

When I convert to NSData using NSKeyedArchiver, does that automatically run the NSCoding protocol? That way I execute that one statement and it will encode everything.
Jonathan, yes, that's how it works. You can call a method like archivedDataWithRootObject to archive an object. That will archive the object and any of it's child objects by calling their NSCoding methods, and return the results as NSData.
And how do you go the other direction?
You use the NSKeyedUnarchiver methods like unarchiveObjectWithData or unarchiveObjectWithFile.
4

NSCoding isn't magic so it will work 'recursively' if your implementation of the encoding and decoding methods tells it to be.

Implement the NSCoding methods and pass the data to be encoded to the encoder. Implement the NSCoding methods in all of your custom classes so that when you encode the array all of the contents can be processed appropriately.

Be sure to call super if the classes superclass also implements NSCoding.

e.g.

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.arrayOfClasses forKey:@"arrayOfClasses"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self.arrayOfClasses = [decoder decodeObjectForKey:@"arrayOfClasses"];
}

5 Comments

So you're saying that if I do implement the NSCoding methods on each custom class it will encode them when I encode that top level array? None of these classes have super classes.
If you implement it to do so. You are passed an NSCoder, you need to tell it what to do. Your classes should at least inherit from NSObject.
Could you show me an example of how to do it? I have never worked with the NSCoding protocol so I'm not exactly sure how to pass an NSCoder to these classes. My classes do inherit from NSObject, I was referring to them not inheriting from another custom super class.
Thank you for adding that code. I do have that implementation in all of my classes, but when I encode the arrayOfClasses, will it automatically encode the objects contained within that array?
It should, have you tested it?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.