Permalink
Browse files

NSCoding

  • Loading branch information...
mikkelee committed Apr 29, 2012
1 parent dfae3d4 commit 679ee1a839564ba065b749372ae7d4ba85f4200f
View
@@ -110,6 +110,29 @@ - (NSComparisonResult)compare:(id)other
return NSOrderedSame;
}
+#pragma mark NSCoding conformance
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super initWithType:[aDecoder decodeObjectForKey:@"type"]];
+
+ if (self) {
+ [self setValue:[aDecoder decodeObjectForKey:@"describedObject"] forKey:@"primitiveDescribedObject"];
+ _value = [aDecoder decodeObjectForKey:@"value"];
+ [self decodeProperties:aDecoder];
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+ [aCoder encodeObject:[self type] forKey:@"type"];
+ [aCoder encodeObject:[self describedObject] forKey:@"describedObject"];
+ [aCoder encodeObject:_value forKey:@"value"];
+ [self encodeProperties:aCoder];
+}
+
#pragma mark Objective-C properties
@synthesize value = _value;
View
@@ -15,7 +15,7 @@
A context provides lookup functionality related to xrefs.
*/
-@interface GCContext : NSObject
+@interface GCContext : NSObject <NSCoding>
/// @name Obtaining a context
View
@@ -35,7 +35,15 @@ + (id)context
- (void)storeXref:(NSString *)xref forEntity:(GCEntity *)obj
{
- [xrefStore setObject:xref forKey:[NSValue valueWithPointer:(const void *)obj]];
+ NSParameterAssert(xref);
+
+ for (NSString *key in [xrefStore allKeysForObject:obj]) {
+ [xrefStore removeObjectForKey:key];
+ }
+
+ //NSLog(@"Storing %@ for %@", xref, obj);
+
+ [xrefStore setObject:obj forKey:xref];
if ([xrefBlocks objectForKey:xref]) {
for (void (^block) (NSString *) in [xrefBlocks objectForKey:xref]) {
@@ -47,27 +55,44 @@ - (void)storeXref:(NSString *)xref forEntity:(GCEntity *)obj
- (NSString *)xrefForEntity:(GCEntity *)obj
{
- NSString *xref = [xrefStore objectForKey:[NSValue valueWithPointer:(const void *)obj]];
+ if (!obj) {
+ return nil;
+ }
+ NSParameterAssert([[obj gedTag] code]);
+
+ //NSLog(@"looking for %@ in %@", obj, self);
+
+ NSString *xref = nil;
+ for (NSString *key in [xrefStore allKeys]) {
+ //NSLog(@"%@: %@", key, [xrefStore objectForKey:key]);
+ if ([xrefStore objectForKey:key] == obj) {
+ xref = key;
+ }
+ }
if (xref == nil) {
int i = 0;
do {
xref = [NSString stringWithFormat:@"@%@%d@", [[obj gedTag] code], ++i];
- } while ([[xrefStore allKeysForObject:xref] count] > 0);
+ } while ([xrefStore objectForKey:xref]);
[self storeXref:xref forEntity:obj];
}
+ //NSLog(@"xref: %@", xref);
+
return xref;
}
- (GCEntity *)entityForXref:(NSString *)xref
{
- return [[[xrefStore allKeysForObject:xref] lastObject] pointerValue];
+ return [xrefStore objectForKey:xref];
}
- (void)registerXref:(NSString *)xref forBlock:(void (^)(NSString *xref))block
{
+ NSParameterAssert(xref);
+
if ([self entityForXref:xref]) {
block(xref);
} else if ([xrefBlocks objectForKey:xref]) {
@@ -77,6 +102,28 @@ - (void)registerXref:(NSString *)xref forBlock:(void (^)(NSString *xref))block
}
}
+#pragma mark NSCoding conformance
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super init];
+
+ if (self) {
+ xrefStore = [aDecoder decodeObjectForKey:@"xrefStore"];
+ xrefBlocks = [aDecoder decodeObjectForKey:@"xrefBlocks"];
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+ [aCoder encodeObject:xrefStore forKey:@"xrefStore"];
+ [aCoder encodeObject:xrefBlocks forKey:@"xrefBlocks"];
+}
+
+#pragma mark Description
+
- (NSString *)description
{
return [NSString stringWithFormat:@"%@: %@", [super description], xrefStore];
View
@@ -93,6 +93,31 @@ - (NSComparisonResult)compare:(id)other
return NSOrderedSame;
}
+#pragma mark NSCoding conformance
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super initWithType:[aDecoder decodeObjectForKey:@"type"]];
+
+ if (self) {
+ _context = [aDecoder decodeObjectForKey:@"context"];
+
+ [self decodeProperties:aDecoder];
+
+ _lastModified = [aDecoder decodeObjectForKey:@"lastModified"];
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+ [aCoder encodeObject:[self type] forKey:@"type"];
+ [aCoder encodeObject:_context forKey:@"context"];
+ [aCoder encodeObject:_lastModified forKey:@"lastModified"];
+ [self encodeProperties:aCoder];
+}
+
#pragma mark Objective-C properties
- (NSOrderedSet *)subNodes
View
@@ -18,7 +18,7 @@
A file keeps a header and a collection of entities.
*/
-@interface GCFile : NSObject
+@interface GCFile : NSObject <NSCoding>
#pragma mark Initialization
@@ -72,7 +72,7 @@
#pragma mark Objective-C properties
/// The header of the receiver.
-@property GCHeader *head;
+@property GCHeader *header;
/// An optional submission entity.
@property GCEntity *submission; //optional
@@ -87,6 +87,9 @@
/// The receiver as an ordered collection of Gedcom nodes.
@property (readonly) NSArray *gedcomNodes;
+/// The receiver as a Gedcom string.
+@property (readonly) NSString *gedcomString;
+
@end
@interface GCFile (GCConvenienceMethods)
View
@@ -42,10 +42,10 @@ - (id)initWithContext:(GCContext *)context gedcomNodes:(NSArray *)nodes;
Class objectClass = [tag objectClass];
if ([objectClass isEqual:[GCHeader class]]) {
- if (_head) {
+ if (_header) {
NSLog(@"Multiple headers!?");
}
- _head = [GCHeader headerWithGedcomNode:node inContext:context];
+ _header = [GCHeader headerWithGedcomNode:node inContext:context];
} else if ([objectClass isEqual:[GCEntity class]]) {
[_entities addObject:[GCEntity entityWithGedcomNode:node inContext:context]];
} else if ([objectClass isEqual:[GCTrailer class]]) {
@@ -64,7 +64,7 @@ - (id)initWithHeader:(GCHeader *)header entities:(NSArray *)entities
self = [super init];
if (self) {
- _head = header;
+ _header = header;
_context = [header context];
_entities = [NSMutableOrderedSet orderedSetWithCapacity:[entities count]];
@@ -101,17 +101,50 @@ - (void)removeEntity:(GCEntity *)entity
[_entities removeObject:entity];
}
+#pragma mark Equality
+
+- (BOOL)isEqualTo:(id)object
+{
+ if (![object isKindOfClass:[self class]]) {
+ return NO;
+ }
+
+ return [[self gedcomString] isEqualToString:[object gedcomString]];
+}
+
+#pragma mark NSCoding conformance
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super init];
+
+ if (self) {
+ _context = [aDecoder decodeObjectForKey:@"context"];
+ _header = [aDecoder decodeObjectForKey:@"header"];
+ _entities = [aDecoder decodeObjectForKey:@"entities"];
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+ [aCoder encodeObject:_context forKey:@"context"];
+ [aCoder encodeObject:_header forKey:@"header"];
+ [aCoder encodeObject:_entities forKey:@"entities"];
+}
+
#pragma mark Objective-C properties
-@synthesize head = _head;
+@synthesize header = _header;
@synthesize submission = _submission;
@synthesize entities = _entities;
- (NSArray *)gedcomNodes
{
NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:[_entities count]+2];
- [nodes addObject:[_head gedcomNode]];
+ [nodes addObject:[_header gedcomNode]];
if (_submission) {
[nodes addObject:[_submission gedcomNode]];
@@ -126,6 +159,17 @@ - (NSArray *)gedcomNodes
return nodes;
}
+- (NSString *)gedcomString
+{
+ NSMutableArray *gedcomStrings = [NSMutableArray array];
+
+ for (GCNode *node in [self gedcomNodes]) {
+ [gedcomStrings addObjectsFromArray:[node gedcomLines]];
+ }
+
+ return [gedcomStrings componentsJoinedByString:@"\n"];
+}
+
@end
@implementation GCFile (GCConvenienceMethods)
View
@@ -20,6 +20,8 @@ @implementation GCHeader {
GCNode *_gedcomNode;
}
+#pragma mark Convenience constructors
+
+ (id)headerWithGedcomNode:(GCNode *)node inContext:(GCContext *)context
{
NSParameterAssert([[node gedTag] isEqualToString:@"HEAD"]);
@@ -31,6 +33,26 @@ + (id)headerWithGedcomNode:(GCNode *)node inContext:(GCContext *)context
return head;
}
+#pragma mark NSCoding conformance
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super init];
+
+ if (self) {
+ _gedcomNode = [aDecoder decodeObjectForKey:@"gedcomNode"];
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+ [aCoder encodeObject:_gedcomNode forKey:@"gedcomNode"];
+}
+
+#pragma mark Objective-C properties
+
@synthesize gedcomNode = _gedcomNode;
@end
View
@@ -290,11 +290,11 @@ - (NSString *)description
- (void)encodeWithCoder:(NSCoder *)encoder
{
- [encoder setValue:[self gedTag] forKey:@"gedTag"];
- [encoder setValue:[self gedValue] forKey:@"gedValue"];
- [encoder setValue:[self xref] forKey:@"xref"];
- [encoder setValue:[self lineSeparator] forKey:@"lineSeparator"];
- [encoder setValue:[self subNodes] forKey:@"subNodes"];
+ [encoder encodeObject:[self gedTag] forKey:@"gedTag"];
+ [encoder encodeObject:[self gedValue] forKey:@"gedValue"];
+ [encoder encodeObject:[self xref] forKey:@"xref"];
+ [encoder encodeObject:[self lineSeparator] forKey:@"lineSeparator"];
+ [encoder encodeObject:[self subNodes] forKey:@"subNodes"];
}
- (id)initWithCoder:(NSCoder *)decoder
View
@@ -20,7 +20,7 @@
Abstract object. Subclasses are GCHeader, GCEntity and GCProperty.
*/
-@interface GCObject : NSObject
+@interface GCObject : NSObject <NSCoding>
#pragma mark Initialization
@@ -200,3 +200,10 @@
- (void)addPropertyWithGedcomNode:(GCNode *)node;
@end
+
+@interface GCObject (GCCodingHelpers)
+
+- (void)decodeProperties:(NSCoder *)aDecoder;
+- (void)encodeProperties:(NSCoder *)aCoder;
+
+@end
Oops, something went wrong.

0 comments on commit 679ee1a

Please sign in to comment.