簡體   English   中英

iPhone中的NSData到NSArray錯誤

[英]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協議,並具有方法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;

貨幣.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表示它不是數組也就不足為奇了。

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

修改后的答案:

因此,這里有三個不同的概念:通用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM