views:

540

answers:

4

Hi,

Someone on IRC told me I could create objective c objects directly from plist files in such a way that I don't have to specify strings everywhere for serialization/deserialization of the plist.

Does anyone know how to do this?

I'd like to simply have a plist like this

<array>
  <object>
    <id>my unique id</id>
    <description>first items description</description>
  </object>
</array>

And somehow deserialize this directly into objective c objects without having to specify the literal string "description" or "id" anywhere in code.

This may not be possible, but I couldn't find anywhere online or on SO that did this or said it's not possible.

Also, I wanted to follow through on what the guy on IRC guy said, but didn't have time to ask him there n then.

Any help is greatly appreciated,

-Vandelizer

+1  A: 

You're looking for class serialization. Apple has a guide here on it's object archival methods. Some keywords for searching are "archival" "NSCoder" and "serialization".

Basically you want to have your class implement the NSCoding interface. You then create the methods -(void)encodeWithCoder:(NSCoder*)coder and - (id)initWithCoder:(NSCoder *)coder. The former is for writing data and the latter will create an object from the data. See the "Encoding and Decoding Objects" section for how you would implement these methods.

Then, when you want to write to a file, you would make an NSArray of your objects, and call [NSKeyedArchiver archiveRootObject:toFile:] to write the array to a file, and [NSKeyedUnarchiver unarchiveObjectWithFile:] to read the file.

ACoolie
+1  A: 

It's worth noting that there are two kinds of archiver; a 'dumb' one, which just persists the object graph, and a 'keyed' one which permits the data structure to evolve over time. The keyed archiver is a much better choice (and the preferred one) since you can then separate the storage element type from the persisted storage time.

AlBlue
A: 

You may or may not be looking for serialization of objects. If you want to read values in an XML plist, and the values therein are all valid plist types, then just suck the XML into an NSString, and send it a -propertyList message. You'll get back an id, the type of which will depend on what was in the plist in question.

  • (id) propertyList Parses the receiver as a text representation of a property list, returning an NSString, NSData, NSArray, or NSDictionary object, according to the topmost element.
NSResponder
A: 

A plist by definition contains any of the following types: array, dictionary, string, real, integer, boolean, date and data). If you are using a true plist you can instantiate the objects it contains with a single line of code. See the NSPropertyListSerialization method:

propertyListFromData:mutabilityOption:format:errorDescription

Binary plists, can contain any objects and can be written and read using the NSKeyedArchiver and NSKeyedUnarchiver. To use these you must adopt the NSCoding protocol here is an example of these methods in an object that inherits from NSObject and has two properties: userId and userEmail.

   + (void) initialize
    {
        [self setVersion:1]; // increment when you object format changes (add or remove properties)
    }

    - (id) initWithCoder:(NSCoder *)coder
    {
        if (self = [super init])
        {
         NSInteger storedClassVersion = [coder versionForClassName:NSStringFromClass([self class])];
         self.userId = [coder decodeObjectForKey:@"userid"];
         self.userEmail = [coder decodeObjectForKey:@"useremail"];
         if (storedClassVersion > 1)
         {
             // Use this block to conditionally read properties in versions greater than 1
         }
        }
        return self;
    }

    - (void) encodeWithCoder:(NSCoder *)coder
    {   
        [coder encodeObject:self.userId forKey:@"userid"];
        [coder encodeObject:self.userEmail forKey:@"useremail"];
    }

When archiving I find it is useful to wrap up all of the objects to be persisted in an NSDictionary. This allows you to find individual objects by key when unarchiving. NSDictionary supports the NSCoding protocol making it really easy to do so.

m4rkk