2012-04-04 80 views
2

稱爲基本上我使用一個名爲OrderedDictionary一些開源代碼是從的NSMutableDictionary的。然後,我想通過將編碼和解碼方法添加到OrderedDictionary類來將有序的字典數據保存到NSUserDefaults。但是,我意識到編碼和解碼方法沒有被調用,因此解碼的字典不再被排序。下面是我的代碼:encodeWithCoder沒有在派生類中的NSMutableDictionary

@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沒有原文:

使用該
/** 
* 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; 
} 

快速示例代碼數據順序以及編碼和解碼方法完全不會被調用。

感謝您提前提供任何幫助! :)

+0

我懷疑有沒有辦法解決這個問題,即我們可能無法調用的NSMutableDictionary的子類的編碼和解碼方法.... – trillions 2012-04-09 17:38:02

回答

3

有一個稱爲-classForCoder,你需要在OrderedDictionary重寫一個NSObject方法。從文檔:

classForCoder
重寫子類中的編碼來代替它自己以外的類。

- (類)classForCoder
返回值
編碼過程中代替接收器自身的類的類。

討論
此方法由NSCoder調用。 NSObject的 實現返回接收者的類。當被存檔 類羣集的專用子類取代他們的公共超類的名稱。

最後一行是關鍵。所以,在OrderedDictionary.m:

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

另外,如果你不使用ARC,請務必保留從-decodeObjectForKey回來的對象。由於搶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

他還需要避免調用'[super initWithCoder:]',除非他也實現了'initWithObjects:forKeys:count:',否則他會崩潰。如果他不調用'[super initWithCoder:]',那麼他也不應該調用'[super encodeWithCoder:]'。 – 2012-04-09 18:14:31

+0

謝謝你抓到那個搶劫。編輯我的答案包括它。 – 2012-04-09 18:17:24

+0

@AndrewMadsen我測試了你所做的改變,效果很好!非常感謝!我們不應該將這個答案添加到原來的OrderedDictionary代碼嗎? :) – trillions 2012-04-10 00:14:58

0

您可能創建一個新的OrderedDictionary與錯誤的初始化,initWithDictionary:。試試這個:

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 2012-04-04 17:16:05

+0

確保在保存默認值時使用'NSKeyedArchiver'。把'NSLog()'放在你的'initWithCoder:'和'encodeWithCoder:'中,看看它們是否被調用並正常工作。 – Costique 2012-04-05 05:04:21

+0

我編輯了包含存檔代碼的答案。 – Costique 2012-04-05 05:10:36