2

基本上我正在使用一些名为 OrderedDictionary 的开源代码,它是从 NSMutableDictionary 派生的。然后我想通过向 OrderedDictionary 类添加编码和解码方法将有序字典数据保存到 NSUserDefaults。但是,我意识到编码和解码方法没有被调用,因此解码的字典不再是有序的。下面是我的代码:

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

在实现文件中:

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

使用它的快速示例代码:

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);

        } 
    }
}

问题是,最终的检索字典没有原始数据顺序,并且根本不调用编码和解码方法。

提前感谢您的帮助!:)

4

2 回答 2

4

有一个调用的 NSObject 方法-classForCoder,您需要在 OrderedDictionary 中重写它。从文档:

classForCoder
被子类覆盖以在编码期间替换其自身以外的类。

-(Class)classForCoder
返回值
在编码期间替换接收者自己的类的类。

讨论
该方法由 NSCoder 调用。NSObject 的实现返回接收者的类。类簇的私有子类在归档时会替换其公共超类的名称。

最后一行是关键。因此,在 OrderedDictionary.m 中:

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

此外,如果您不使用 ARC,请确保保留从-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;
}
于 2012-04-09T18:04:34.290 回答
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"];
于 2012-04-04T04:53:05.987 回答