PropertyListFaultHandler example
From EOFWiki
Contents |
What we like to do
The supplied Foundation method +[NSMutableDictionary dictionaryWithContentsOfFile:pathname] doesn't load the dictionary lazily. We'd like to emploay the EOFault technology to create a lazy NSMutableDictionary class method named dictionaryByReferencingFile similiar to the NSImage method -[NSImage initByReferencingFile:].
Can we do it ?
First of all we need to check that NSMutableDictionary is large enough for an EOFault. If it isn't, than we'd need to create our own NSMutableDictionary subclass. We assume it's large enough.
We don't need an EOFault subclass
EOFault is never subclassed. All the custom logic is part of the handler. So there's nothing to do here.
We do need our own EOFaultHandler
#import <EOControl/EOControl.h>
@interface EOPropertyListFaultHandler : EOFaultHandler
{
id _pathname;
}
- initByReferencingFile:(NSString *) path;
@end
#import "PropertyListFileFaultHandler.h"
@implementation PropertyListFileFaultHandler
- (id) initByReferencingFile:(NSString *) path
{
[super init];
_pathname = [path copy];
return self;
}
- (void) dealloc
{
[_pathname release];
[super dealloc];
}
- (NSDictionary *) propertyList
{
id plist;
NSPropertyListFormat format;
NSString *error;
NSData *data;
error = nil;
data = [NSData dataWithContentsOfFile:_pathname];
plist = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
[error autorelease];
return plist;
}
- (void) completeInitializationOfObject:(id) obj
{
id plist;
plist = [self propertyList];
// clearing the fault releases self (the EOFaultHandler), so keep it around some more
[[self retain] autorelease];
[EOFault clearFault:obj];
[obj setDictionary:plist];
}
@end
Let's add a Category to make it smooth
@interface NSMutableDictionary (LazyLoading)
+ dictionaryByReferencingFile:(NSString *) path;
@end
@implementation NSMutableDictionary (LazyLoading)
- initByReferencingFile:(NSString *) path
{
EOFaultHandler *handler;
self = [self init]; // may turn placeholder into real
handler = [[[PropertyListFileFaultHandler alloc] initByReferencingFile:path] autorelease];
[EOFault makeObjectIntoFault:self
withHandler:handler];
return self;
}
+ dictionaryByReferencingFile:(NSString *) path
{
return [[self alloc] initByReferencingFile:path] autorelease];
}
@end
Question and Answers
Why is a NSMutableDictionary and not a NSDictionary used ?