Reputation: 1208
I'm updating an existing app to follow the MVC design. I created a top level data Model class. In this dataModel class I archive and dearchive a children array (self.children). This is an array of Child objects with an items property. The items property is an array of BabyMilestone objects. Both the Child class and the BabyMilestone class take care of encode/decoding themselves. The objects in the Child class are being properly encoded and decoded. The objects in the BabyMilestone class are not. Encode with coder is NOT being called on the BabyMilestone objects but is being called on Child class.
Question : Do I need to do something special to encode an array of objects that is a property of something else? Any debugging suggestions welcome!
The top level DataModel class which handles the saving and loading of the .plist
@implementation DataModel
-(id)init
{
if ((self = [super init]))
{
[self loadBabyMilestones];
}
return self;
}
/////////////Loading and Saving Methods////////////////
//Path to documentsDirectory for loading and saving the .plist file of BabyMilestone Objects
-(NSString *)documentsDirectory
{ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
return documentsDirectory;
}
-(NSString *)dataFilePath
{ return [[self documentsDirectory] stringByAppendingPathComponent:@"BabyMilestones.plist"];
NSLog(@"The documents directory is %@", [self documentsDirectory]);
}
//Save the BabyMilestoneitems to the .plist
-(void) saveBabyMilestoneItems
{
Child *child;
child = [[Child alloc] init];
child = [self.children objectAtIndex:0 ];
NSLog(@"The length of the children array in the SAVE method is %lu", child.items.count);
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:self.children forKey:@"Children"];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
NSLog(@"In saveBabyMilestoneItems");
}
//Loading the babyMilestones data from the .plist file
-(void) loadBabyMilestones
{
NSString *path = [self dataFilePath];
NSLog(@"Data file path is %@", [self dataFilePath]);
if ([[NSFileManager defaultManager]fileExistsAtPath:path]) //if file exists load self.children
{
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
self.children = [unarchiver decodeObjectForKey:@"Children"];
[unarchiver finishDecoding];
NSLog(@"In loadbabymilestones loading from file");
}
//Default list
else {
self.children = [[NSMutableArray alloc]initWithCapacity:2];
Child *child;
child = [[Child alloc] init];
child.name = @"Test Child 1";
[self.children addObject:child];
child = [[Child alloc]init];
child.name = @"Test Child 2";
[self.children addObject:child];
for (Child *child in self.children) {
babyMilestone *babyItem;
babyItem = [[babyMilestone alloc] init];
babyItem.text = @"Arrives Home";
babyItem.backgroundImageName = @"newText_home";
babyItem.imageName = @"Flat_Home_Icon.png";
babyItem.textDescription = nil;
babyItem.highResImage = @"newText_homehighRes.jpg";
babyItem.newItem = NO;
babyItem.date = nil;
babyItem.nativeItem = YES;
babyItem.photoID = @-1;
[child.items addObject:babyItem];
}
}
}
@end
The BabyMilestone Class (encodewithcoder never called)
#import "babyMilestone.h"
@implementation babyMilestone
-(id)initWithCoder:(NSCoder *)aDecoder
{
if ((self=[super init])) {
self.textDescription = [aDecoder decodeObjectForKey:@"TextDescription"];
self.text = [aDecoder decodeObjectForKey:@"Text"];
self.photoID = [aDecoder decodeObjectForKey:@"PhotoID1"];
self.imageName = [aDecoder decodeObjectForKey:@"Thumbnail"];
self.date = [aDecoder decodeObjectForKey:@"Date"];
self.backgroundImageName = [aDecoder decodeObjectForKey:@"BackgroundImage"];
self.highResImage = [aDecoder decodeObjectForKey:@"HighResImage"];
self.nativeItem = [aDecoder decodeBoolForKey:@"NativeItem"];
}
return self;
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.textDescription forKey:@"TextDescription"];
[aCoder encodeObject:self.text forKey:@"Text"];
[aCoder encodeObject:self.photoID forKey:@"PhotoID1"];
[aCoder encodeObject:self.imageName forKey:@"Thumbnail"];
[aCoder encodeObject:self.date forKey:@"Date"];
[aCoder encodeObject:self.backgroundImageName forKey:@"BackgroundImage"];
[aCoder encodeObject:self.highResImage forKey: @"HighResImage"];
[aCoder encodeBool:self.nativeItem forKey:@"NativeItem"];
NSLog(@"In encode with coder in babymilestone.m");
}
@end
Child Class
#import "Child.h"
@implementation Child
- (id)init { //Used when user add a new child
if ((self = [super init])) {
self.items = [[NSMutableArray alloc] initWithCapacity:20];
}
return self; }
-(id)initWithCoder:(NSCoder *)aDecoder //Load existing children
{
if ((self=[super init])) {
self.name = [aDecoder decodeObjectForKey:@"Name"];
//self.birthday = [aDecoder decodeObjectForKey:@"Birthday"];
NSLog(@"Init with coder being called on Child class");
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"Name"];
NSLog(@"Encodewithcoder is called in the Child class");
//[aCoder encodeObject:self.birthday forKey: @"Birthday];
}
@end
Upvotes: 0
Views: 303
Reputation: 14824
Your Child
objects, as the keepers of the babyMilestones
, are the ones responsible for encoding them. Add [aCoder encodeObject:self.items forKey:@"Items"];
to Child
's encodeWithCoder:
. This way, when a Child
is told to encode, it will encode its babyMilestones
as well.
Upvotes: 3