[英]NSData to NSArray error in iPhone
我正在使用NSURLConnection從服務器獲取XML數據。 我正在解析數據並將其顯示在表格視圖中。 一切都按預期工作。 現在,我想保存下載的數據以供離線使用。 想法是下載下載的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)'
為什么會這樣呢? 什么是可可錯誤3840?
我的對象實現了NSCoding協議,並具有方法encodeWithCoder
和initWithCoder
。 我的對象的每個屬性都必須進行編碼/解碼嗎?
編輯:這是我的對象:
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;
貨幣.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
為什么不將NSData對象直接保存到帶有
data writeToFile:(NSString*)path atomically:(BOOL)flag
?
我不認為您在NSPropertyList調用中遇到錯誤-如果發生錯誤, propertyListWithData函數將返回nil ,並且我認為該錯誤僅在那時才有效。 您可能應該檢查返回值!= nil,然后打印錯誤。 錯誤3840標志着屬性列表錯誤范圍的開始,它本身看起來並不像錯誤。
對propertyListWithData的描述還說它返回一個屬性列表 ,而不是數組,因此isKindOfClass表示它不是數組也就不足為奇了。
修改后的答案:
因此,這里有三個不同的概念:通用XML,propertyList(以二進制或XML格式)和存檔。 您可以使用NSXMLParser或其他庫來解析XML,以將其轉換為Obj-C對象。 您可以將核心Obj-C對象(不包括自定義類Currency)保存到屬性列表中,然后將其讀回。 或者,您可以將任何對象/對象圖(使用編碼器)存檔到存檔中,然后使用NSKeyedUnarchiver讀回。
即使它們可以共享實現,您也不能混合使用。 例如,首先您嘗試將XML讀取為propertyList,即使pLists是XML,您的通用CurrencyData XML的plist格式也不正確(例如no)。 另外,即使您要寫出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的模型,為什么不序列化該數據副本而不是原始流呢?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.