2011-10-24 11 views
2

NSURLConnectionを使用してサーバーからXMLデータを取得しています。私は、データを解析し、それをテーブルビューで表示しています。それはすべて期待通りに機能します。今、オフラインで使用するためにダウンロードしたデータを保存したいと思います。アイデアはNSDataをダウンロードしてNSArrayに変換し、NSUserDefaultsまたは別のファイルに保存することでした。しかし、NSDataをNSArrayに変換する際に問題が発生しています。iPhoneで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 
+0

データとは何ですか? NSCoding実装の実装を投稿します。 – logancautrell

答えて

0

の説明propertyListWithDataもここを参照してください...それはisKindOfClassは、それが配列でないと言うことは驚くべきことではないので、それは、プロパティリストではなく、配列を返すことを言います

改訂版の回答:

一般的なXML、プロパティリスト(バイナリ形式またはXML形式のいずれか)、およびアーカイブの3つの異なる概念があります。 Obj-Cオブジェクトに変換するために、NSXMLParserまたは他のライブラリを使用してXMLを解析します。カスタムObj-Cオブジェクト(カスタムクラスの通貨を含まない)をプロパティリストに保存して読み戻すことができます。または、オブジェクト/オブジェクトグラフ(エンコーダを使用)をアーカイブにアーカイブし、NSKeyedUnarchiverを使用してそれを読み取ることができます。

実装の下にあるものの、実装を共有することはできますが、それらを混在させることはできません。たとえば、まずXMLをpropertyListとして読み込もうとしましたが、pListsがXMLであっても、一般的なCurrencyData XMLはplistの正しい書式(noなど)を持っていません。さらに、plistを書いていたとしても、それをplistで保存できるようにCurrencyをNSDictionaryに変換する必要があります。つまり、エンコーダは必要ありません。

次に、NSKeyedUnarchiverでXMLを読み込もうとしましたが、メッセージに「理解できないアーカイブ」があります。また、NSKeyedArchiveで作成されていないので修正してください。

元のストリームを使用したり、オブジェクトに直接plistまたはunarchiveすることはできません。しかし、解析された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

これは私がやったことです。私はまだ上記のコードが動作していないのだろうと思っています。 – Maggie

+1

わかりませんが、いくつかの可能なパス:まずXMLはありませんが、NSArrayではなくNSDictionaryとして入力されると思います。 NSLog(@ "データクラス:%@"、[[データクラス]の説明])をチェックします。次に、エラーからより有用な情報を得ることができます。第2の答えはこちらをご覧ください:http://stackoverflow.com/questions/1283960/iphone-core-data-unresolved-error-while-saving/1297157第3に、XMLとキー付きアーカイブが混在している可能性があります。 NSKeyedUnarchive、AFAIKは、任意のXMLではなくNSKeyedArchiveによって書き込まれたデータのみを読み取ることができます。最後に、基本クラスだけのオブジェクトのコーダーは必要ないと思います。 – mackworth

+0

私はNSDictionaryのようではありません...とにかく、あなたの助けに感謝します。私が得ているエラーは次のとおりです: NSDebugDescription = "2行目で未知のタグの通貨が見つかりました"; kCFPropertyListOldStyleParsingError = "エラードメイン= NSCocoaErrorDomainコード= 3840 \"操作を完了できませんでした。 (1行目の不正なデータバイトグループ、無効な16進数)UserInfo = 0x625bc70 {NSDebugDescription = 1行目の不正なデータバイトグループ、無効な16進数} "; – Maggie

0

あなただけたNSDataを保存しない理由はありますファイルに直接オブジェクトを挿入する

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

私はあなたのNSPropertyList呼び出しでエラーが出るとは思わない - エラーが発生した場合propertyListWithData機能ははnilを返し、私はエラーがだけにして有効であると仮定します。おそらく戻り値!= nilでチェックしてから、エラーを出力してください。エラー3840は、プロパティリストエラーの範囲の開始を示します。これは、エラーのようには見えません。

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

関連する問題