iPhone中的NSData到NSArray错误

问题描述 投票:2回答:2

我正在使用NSURLConnection从服务器获取XML数据。我正在解析数据并在tableview中显示它。这一切都按预期工作。现在,我想保存下载的数据以供离线使用。我们的想法是下载NSData,将其转换为NSArray并将其存储到NSUserDefaults或单独的文件中。但是,我在将NSData转换为NSArray时遇到问题。

我在(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data方法中添加了逻辑。我想做的是如下:

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");
}

在日志中我得到如下:

错误无法完成操作。 (可可错误3840.)

不是数组

如果我删除错误处理并留下线

NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data];

我的应用程序崩溃时出现以下消息:`

因未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'*** - [NSKeyedUnarchiver initForReadingWithData:]:难以理解的存档(0x3c,0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65)'

为什么会这样?什么是Cocoa错误3840?

我的对象实现了NSCoding协议,并且有encodeWithCoderinitWithCoder方法。我的对象的每个属性都必须编码/解码吗?

编辑:这是我的对象: 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
iphone objective-c ios
2个回答
0
投票

修改回答:

因此,这里有三个不同的概念:通用XML,propertyLists(二进制或XML格式)和Archive。您使用NSXMLParser或其他库解析XML以转换为Obj-C对象。您可以将核心Obj-C对象(不包括您的自定义类货币)保存到属性列表中并将其读回。或者,您可以将任何对象/对象图(使用编码器)存档到存档中,并使用NSKeyedUnarchiver将其读回。

即使它们下面可能共享实现,也不能混合它们。例如,首先您尝试将XML作为propertyList读取,即使pLists是XML,您的通用CurrencyData XML也没有正确的plist格式(例如,否)。另外,即使你要写一个plist,你也必须将Currency转换为NSDictionary才能使它在plist中存储,这意味着你不需要编码器。

然后,您尝试使用NSKeyedUnarchiver读取XML并获得消息“难以理解的存档”。同样正确,因为它不是用NSKeyedArchive创建的。

因此,您无法使用原始流并直接在您的对象中删除或取消归档。但是要保存解析后的XMLArray以供离线使用,您可以将Currency转换为NSDictionary并使用属性列表,或者只是保持原样,并使用NSKeyedArchive和Unarchive这样(利用您提供的编码器/解码器):

//To save
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:xmlArray];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"myKey"]; //or store in another file

//To later read
NSData * data2 = [[NSUserDefaults standardUserDefaults] valueForKey:@"myKey"];
NSArray * newXMLArray = [NSKeyedUnarchiver unarchiveObjectWithData:data2];

希望能搞清楚。调查它也清除了我自己对何时使用哪种技术的理解。

//原始评论:如果您已将传入数据解析为tableView的模型,为什么不序列化该数据副本而不是原始流?


0
投票

您是否有理由不直接将NSData对象保存到文件中

data writeToFile:(NSString*)path atomically:(BOOL)flag

?

我认为你的NSPropertyList调用没有错误 - 如果发生错误,propertyListWithData函数返回nil,我认为错误只有在那时才有效。你可能应该检查返回值!= nil,然后打印错误。错误3840表示属性列表错误范围的开始,它本身看起来不像错误。

propertyListWithData的描述也说它返回一个属性列表,而不是一个数组,所以isKindOfClass说它不是一个数组就不足为奇了......看到这里:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSPropertyListSerialization_Class/Reference/Reference.html

© www.soinside.com 2019 - 2024. All rights reserved.