Re: Property List Question
Re: Property List Question
- Subject: Re: Property List Question
- From: Brian Hill <email@hidden>
- Date: Thu, 17 May 2001 19:31:49 -0500
On Thursday, May 17, 2001, at 01:26 PM, mmalcolm crawford wrote:
If your data model is subject to change (you add instance variables
etc), then NSArchiving does allow you to store a version number in your
files. You can then write your "read in" methods appropriately to take
account of old versions of the data. What NSArchiving doesn't allow
you to do is save a file in a previous format (e.g. without the
instance variables you added in later versions).
I've been using another useful Cocoa design pattern that helps deal with
backward compatibility with your programs file format: Whenever
possible, don't use separate instance variables -- use a single
NSMutableDictionary instead.
You can still write nice accessor methods that simply set and retrieve
the keyed values for each 'virtual instance variable' (I just made that
up...). However, if you add several more 'bits-o-data' that your data
model objects need to track, you can just add more accessor methods and
use new keys for the new 'bits'. The advantage is that the object is
still binary compatible with previous versions (since you've only added
methods -- not instance variables).
Also, once you start doing this, it gets *very* easy to store the object
as an XML file. Most of my data model objects work this way, and just
include a 'initWithAttributes:(NSDictionary*)attr' for re-creating from
XML, and an '(NSDictionary*)attributes' method for storing the object's
data.
In short, instead of doing this:
@interface MyObject: NSObject
{
NSString* name;
NSString* address;
NSString* phone;
}
...accessor methods
@end
Do this:
@interface MyObject:NSObject
{
NSMutableDictionary* attributes;
}
- initWithDictionary:(NSDictionary*)inAttributes;
- (NSDictionary*)attributes;
..same accessor methods
@end
Then the accessor methods can just look like this:
- (NSString*)name
{
return [attributes valueForKey:@"name"];
}
- (void)setName:(NSString*)inName
{
[attributes takeValue:inName forKey:@"name"];
//takeValue:forKey is actually better than 'setObject:forKey: here,
since it just removes the
//key and previous value if the new value is nil, instead of
throwing an exception.
}
There is also a way of implementing key-value coding on an object like
this, ie., you can forward the 'takeValue:forKey:' to the attributes
dictionary. If you name your attribute keys properly (ie., store the
'name' attribute with the key 'name'), you can get away with not even
implementing the accessor methods at all! (the 'magic' of key-value
coding does this).
Anyway, I didn't invent this idea -- I stole it from ObjC/EOF...8-)
Brian
email@hidden
http://personalpages.tds.net/~brian_hill
"Why? I came into this game for adventure - go anywhere, travel
light, get in, get out, wherever there's trouble, a man alone.
Now they've got the whole country sectioned off and you can't
move without a form. I'm the last of a breed."
-- Archibald "Harry" Tuttle, Rogue HVAC Repairman