I am using NSURLConnection to fetch XML data from the server. I am parsing the data and showing it in a tableview. It all works as expected. Now, I would like to save downloaded data for an offline use. The idea was to take downloaded NSData, convert it to NSArray and store it either to NSUserDefaults or in a separate file. However, I am having problems converting NSData to NSArray.
I added the logic to (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data method. What I am trying to do is as follows:
NSError *error;
NSPropertyListFormat plistFormat;
id object = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&plistFormat error:&error];
if (error != nil) {
NSLog(@"Error %@", [error localizedDescription]);
[error release];
}
if ([object isKindOfClass:[NSArray class]]) {
NSLog(@"IS Array");
NSArray *objectArray = object;
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"myKey"];
} else {
NSLog(@"Not an array");
}
In log I get as follows:
Error The operation couldn’t be completed. (Cocoa error 3840.)
Not an array
If I remove error handling and leave just the line
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
my application crashes with the following message: `
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65)'
Why is this happening? What is Cocoa error 3840?
My object implements NSCoding protocol, and has methods encodeWithCoder and initWithCoder. Does every property of my object has to be encoded / decoded?
Edit: Here is my object:
Currency.h
@interface Currency : NSObject<NSCoding>{
CGFloat value;
NSString *code;
NSDate *date;
NSString *description;
NSString *imagePath;
}
@property (nonatomic, assign) CGFloat value;
@property (nonatomic, retain) NSString *code;
@property (nonatomic, retain) NSDate *date;
@property (nonatomic, retain) NSString *description;
@property (nonatomic, retain) NSString *imagePath;
Currency.m
@implementation Currency
@synthesize value;
@synthesize code;
@synthesize date;
@synthesize description;
@synthesize imagePath;
static NSString * const keyCode = @"code";
static NSString * const keyDescription = @"description";
static NSString * const keyValue = @"value";
- (void)dealloc {
[code release];
[date release];
[description release];
[imagePath release];
[super dealloc];
}
- (void)encodeWithCoder:(NSCoder *)coder
{
if ([coder allowsKeyedCoding]) {
[coder encodeObject:code forKey: keyCode];
[coder encodeObject:description forKey: keyDescription];
[coder encodeFloat:value forKey: keyValue];
}
}
}
- (id)initWithCoder:(NSCoder *) coder {
self = [[Currency alloc] init];
if (self != nil)
{
code = [[coder decodeObjectForKey:keyCode] retain];
description = [[coder decodeObjectForKey:keyDescription] retain];
value = [coder decodeFloatForKey:keyValue];
}
return self;
}
@end