2

I am trying to save an NSDictionary to my NSUserDefualts.

The dictionary consists of 3 different custom classes.

@interface PastOrder : NSObject <NSCoding>
{
    NSDate *timeIn;
    NSDate *timeOut;
    NSString *status;
    NSMutableArray *myItems;
}

@property (nonatomic, retain) NSDate *timeIn;
@property (nonatomic, retain) NSDate *timeOut;
@property (nonatomic, retain) NSString *status;
@property (nonatomic, retain) NSMutableArray *myItems;

@end
@implementation PastOrder

@synthesize timeIn, timeOut, status, myItems;
#define PastOrderTimeInKey @"PastOrderTimeInKey"
#define PastOrderTimeOutKey @"PastOrderTimeOutKey"
#define PastOrderStatusKey @"PastOrderStatusKey"
#define PastOrderMyItemsKey @"PastOrderMyItemsKey"

-(id)initWithCoder:(NSCoder*)decoder
{
    self = [super init];
    if(self)
    {
        self.timeIn = [decoder decodeObjectForKey:PastOrderTimeInKey];
        self.timeOut = [decoder decodeObjectForKey:PastOrderTimeOutKey];
        self.status = [decoder decodeObjectForKey:PastOrderStatusKey];
        self.myItems = [decoder decodeObjectForKey:PastOrderMyItemsKey];
    }
    return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder
{
    [encoder encodeObject:self.timeIn forKey:PastOrderTimeInKey];
    [encoder encodeObject:self.timeOut forKey:PastOrderTimeOutKey];
    [encoder encodeObject:self.status forKey:PastOrderStatusKey];
    [encoder encodeObject:self.myItems forKey:PastOrderMyItemsKey];
}
-(void)dealloc
{
    self.timeIn = nil;
    self.timeOut = nil;
    self.status = nil;
    self.myItems = nil;
}
@end

@interface PastOrderItem : NSObject <NSCoding>
{
    NSNumber *itemID;
    NSString *status;
    NSMutableArray *itemChoices;
}
@property (nonatomic, retain) NSNumber *itemID;
@property (nonatomic, retain) NSString *status;
@property (nonatomic, retain) NSMutableArray *itemChoices;
@end
@implementation PastOrderItem

@synthesize itemID,status,itemChoices;
#define PastOrderItemItemIDKey @"PastOrderItemItemIDKey"
#define PastOrderItemStatusKey @"PastOrderItemStatusKey"
#define PastOrderItemItemChoicesKey @"PastOrderItemItemChoicesKey"
-(id)initWithCoder:(NSCoder*)decoder
{
    self = [super init];
    if(self)
    {
        self.itemID = [decoder decodeObjectForKey:PastOrderItemItemIDKey];
        self.itemChoices = [decoder decodeObjectForKey:PastOrderItemItemChoicesKey];
        self.status = [decoder decodeObjectForKey:PastOrderItemStatusKey];
     }
    return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder
{
    [encoder encodeObject:self.itemID forKey:PastOrderItemItemIDKey];
    [encoder encodeObject:self.itemChoices forKey:PastOrderItemItemChoicesKey];
    [encoder encodeObject:self.status forKey:PastOrderItemStatusKey];
}
-(void)dealloc
{
    self.itemID = nil;
    self.itemChoices = nil;
    self.status = nil;
}
@end

@interface PastOrderItemChoice : NSObject <NSCoding>
{
    NSNumber *modifierID;
    NSNumber *modifierChoice;
}
@property (nonatomic, retain) NSNumber *modifierID;
@property (nonatomic, retain) NSNumber *modifierChoice;
@end
@implementation PastOrderItemChoice

@synthesize modifierID, modifierChoice;
#define PastOrderItemChoiceModifierIDKey @"PastOrderItemChoiceModifierIDKey"
#define PastOrderItemChoiceModifierChoiceKey @"PastOrderItemChoiceModifierChoiceKey"
-(id)initWithCoder:(NSCoder*)decoder
{
    self = [super init];
    if(self)
    {
        self.modifierID = [decoder decodeObjectForKey:PastOrderItemChoiceModifierIDKey];
        self.modifierChoice = [decoder decodeObjectForKey:PastOrderItemChoiceModifierChoiceKey];
     }
    return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder
{
    [encoder encodeObject:self.modifierID forKey:PastOrderItemChoiceModifierIDKey];
    [encoder encodeObject:self.modifierChoice forKey:PastOrderItemChoiceModifierChoiceKey];
}
-(void)dealloc
{
    self.modifierID = nil;
    self.modifierChoice = nil;

}
@end

Those are the three classes that will be inside this NSDictionary. Here is how I Load and Save it.

-(void)SavePrefs
{
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    NSData* data=[NSKeyedArchiver archivedDataWithRootObject:self.myDictionary];
    [prefs setObject:data forKey:@"SavedOrders"];
    [prefs synchronize];
}
- (id)init
{
    self = [super init];
    if (self)
    {
        NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:@"SavedOrders"];
        self.myDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];

      }
    return self;
}

I have experimented with the code a bit, and best I have to far, is that when I save the dictionary, it was 135 bytes, same as when I loaded it, but it still didnt fill the dictionary up. So I am at a loss.

Scott Modra
  • 29
  • 1
  • 3

1 Answers1

1

Your code seems to be good. I can't find a mistake so try to change line:

self.myDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];

to

id unknownObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"%@",[unknownObject class]);

And look @ the console. Maybe you should also try casting if the output will be dictionary. So try to change this to:

self.myDictionary = (NSDictionary*)[NSKeyedUnarchiver unarchiveObjectWithData:data];

EDIT

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"object1",@"key1",@"object2",@"key2",@"object3",@"key3", nil];
NSLog(@"before: %@",dictionary);
NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:dictionary];
NSDictionary *myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:myData];
NSLog(@"after: %@",myDictionary);

Output:

2013-11-13 14:32:31.369 DemoM[175:60b] before: {
    key1 = object1;
    key2 = object2;
    key3 = object3;
}
2013-11-13 14:32:31.372 DemoM[175:60b] after: {
    key1 = object1;
    key2 = object2;
    key3 = object3;
}
Jakub
  • 13,712
  • 17
  • 82
  • 139
  • 1
    when you archive i thought you had to have encode with coder and also implement the init with coder initializer method in all the objects being encoded/decoded – A'sa Dickens Nov 13 '13 at 13:32
  • I don't think so.. I just write a sample piece of code, and works fine. – Jakub Nov 13 '13 at 13:36
  • alrighty, if it works it works :D – A'sa Dickens Nov 13 '13 at 13:43
  • Your first example didnt work, but the second one did. But when I changed it to use my saved data, it returns a null dictionary. – Scott Modra Nov 13 '13 at 14:19
  • The dictionary to data that you have going on shows the data type at 364 bytes, already more than double the size of my saved dictionary. This cant be right, so the dictionary must be saving wrong. If I have custom classes in the custom class arrays, I dont need to change those to data as well do I? – Scott Modra Nov 13 '13 at 14:22