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