2012-04-04 16 views
2

基本的に、NSMutableDictionaryから派生したOrderedDictionaryというオープンソースコードを使用しています。次にOrderedDictionaryクラスにencodeメソッドとdecodeメソッドを追加して、順序付き辞書データをNSUserDefaultsに保存します。しかし、エンコードとデコードのメソッドが呼び出されていないことに気付きました。その結果、デコードされた辞書はもはや順序付けされません。以下は私のコードは次のとおりです。これを使用するためのNSMutableDictionaryの派生クラスでencodeWithCoderが呼び出されない

/** 
* encode the object 
**/ 
- (void)encodeWithCoder:(NSCoder *)coder 
{ 
    [super encodeWithCoder:coder]; 
    [coder encodeObject:dictionary forKey:@"dictionary"]; 
    [coder encodeObject:array forKey:@"array"]; 
} 

/** 
* decode the object 
*/ 
- (id)initWithCoder:(NSCoder *)coder 
{ 
    self = [super initWithCoder:coder]; 
    if (self != nil) 
    { 
     dictionary = [coder decodeObjectForKey:@"dictionary"]; 
     array = [coder decodeObjectForKey:@"array"]; 
    } 
    return self; 
} 

クイックサンプルコード:実装ファイルで

@interface OrderedDictionary : NSMutableDictionary <NSCopying, NSCoding> 
{ 
    NSMutableDictionary *dictionary; 
    NSMutableArray *array; 
} 

dictionary = [[OrderedDictionary alloc] init]; 
[dictionary setObject:@"one" forKey:@"two"]; 
[dictionary setObject:@"what" forKey:@"what"]; 
[dictionary setObject:@"7" forKey:@"7"]; 
NSLog(@"Final contents of the dictionary: %@", dictionary); 

if ([[NSUserDefaults standardUserDefaults] objectForKey:@"myDictionary"] == nil) 
{ 
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:dictionary] 
              forKey:@"myDictionary"]; 
} 
else 
{ 
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults]; 

    NSData *savedDictionary = [currentDefaults objectForKey:@"myDictionary"]; 

    if (savedDictionary != nil) 
    { 
     OrderedDictionary *oldData = [NSKeyedUnarchiver unarchiveObjectWithData:savedDictionary]; 
     if (oldData != nil) 
     { 
      NSLog(@"Final contents of the retrieved: %@", oldData); 

     } 
    } 
} 

事がされ、最終的retrievedDictionaryはオリジナルを持っていませんデータの順序とエンコードとデコードのメソッドはまったく呼び出されません。

事前にお問い合わせいただきありがとうございます。 :)

+0

、すなわち、私たちはNSMutableDictionaryの子クラスのエンコードとデコードメソッドを呼び出すことができない場合があり.... – trillions

答えて

3

あなたはOrderedDictionaryでオーバーライドする必要が-classForCoder呼ばNSObjectの方法があります:デフォルトを保存するためのコードは、このようなものを含める必要があります。ドキュメントから:

classForCoder
コーディングの際に、自社以外のクラスを置き換えるためにサブクラスによってオーバーライドされます。

- (クラス)classForCoder
戻り値
コーディング中に受信機自身のクラスの代わりにするクラス。

説明
このメソッドは、NSCoderによって呼び出されます。 NSObjectの 実装は受信側のクラスを返します。 のプライベートサブクラスは、 がアーカイブされているときに、そのクラスのパブリックスーパークラスの名前で置き換えられます。

最後の行がキーです。だから、OrderedDictionary.mに:あなたはARCを使用していない場合は

また
- (Class)classForCoder 
{ 
    return [self class]; // Instead of NSMutableDictionary 
} 

、あなたが-decodeObjectForKeyから戻ってくるオブジェクトを保持してください。 rob mayoffが以下に言及しているように、[super initWithCoder:](または[super encodeWithCoder:')に電話するべきではありません。私も衝突を避けるためにキーストリングを変更しました。私はそれを修正する方法はありません疑う

- (id)initWithCoder:(NSCoder *)coder 
{ 
    if (self != nil) 
    { 
     dictionary = [[coder decodeObjectForKey:@"OrderedDictionary_dictionary"] retain]; 
     array = [[coder decodeObjectForKey:@"OrderedDictionary_array"] retain]; 
    } 
    return self; 
} 
+0

彼は 'initWithObjects:forKeys:count:'も実装していない限り、 '[super initWithCoder:]'を呼び出すことを避ける必要があります。そうしないと、クラッシュします。そして彼が '[super initWithCoder:]'を呼んでいなければ、 '[super encodeWithCoder:]'を呼ぶべきではありません。 –

+0

そのロブをキャッチするためにありがとう。それを含めるために私の答えを編集しました。 –

+0

@AndrewMadsen私はあなたが行った変更をテストした、うまくいった!どうもありがとうございます!元のOrderedDictionaryコードにこの回答を追加するべきではありませんか? :) – trillions

0

の間違った初期設定で新しいOrderedDictionaryを作成している可能性があります。代わりにこれを試してみてください:

OrderedDictionary *oldData = [NSKeyedUnarchiver unarchiveObjectWithData: savedDictionary]; 
if (oldData != nil) 
{ 
    NSLog(@"Final contents of the retrieved: %@", oldData); 
} 

initWithDictionary:が引数としてOrderedDictionaryを期待していることを確認します。私の推測では、それはNSDictionaryを期待しています。

編集:

OrderedDictionary *myDict = ...; 
NSData* data = [NSKeyedArchiver archivedDataWithRootObject: myDict]; 
[[NSUserDefaults standardDefaults] setObject: data forKey: @"myDictionary"]; 
+0

はあなたの助けをありがとうございました。私はあなたのやり方を試しました。出力はまだ正しくない、データの順序はもはや予約されていない。あなたが行った変更を反映するためにこの投稿のコードを更新しました。私は問題が私のencodeWithCoderは全く呼び出されていないと思うので、親クラス(NSMutableDictionary)のエンコードとデコードのメソッドが呼び出されました。しかし、私はこれを修正する方法を知らない。 – trillions

+0

デフォルトを保存するときは必ず 'NSKeyedArchiver'を使用してください。あなたの 'initWithCoder:'と 'encodeWithCoder:'に 'NSLog()'を入れて、それらが正しく呼び出され、正しく動作するかどうか確認してください。 – Costique

+0

私はアーカイブコードを含める答えを編集しました。 – Costique

関連する問題