包含自定义对象的NSMutableDictionaries的NSCoding

时间:2010-12-03 09:23:26

标签: ios nsmutabledictionary nscoding

我正在尝试序列化包含SearchEntity的{​​{1}}对象(自定义对象),其中包含一组类型为NSMutableDictionary的自定义对象。

1 CategoryEntity包含:   1 SearchEntity<NSCoding>(参数)     包含的参数      X NSMutableDictionary只包含字符串和数字。

在SearchEntity encodeWithCoder的这一行CategoryEntities<NSCoding>“我得到GDB:每次都中断,没有错误信息,异常等只是GDB:中断。

这是[encoder encodeObject:parameters forKey:kPreviousSearchEntityKey];中的实现,参数是SearchEntity

NSMutableDictionary

#pragma mark - #pragma mark NSCoding delegate methods - (void) encodeWithCoder:(NSCoder*)encoder { //encode all the values so they can be persisted in NSUserdefaults if (parameters) [encoder encodeObject:parameters forKey:kPreviousSearchEntityKey]; //GDB:Interrupted! } - (id) initWithCoder:(NSCoder*)decoder { if (self = [super init]) { //decode all values to return an object from NSUserdefaults in the same state as when saved [self setParameters:[decoder decodeObjectForKey:kPreviousSearchEntityKey]]; } return self; } 也实现了NSCoding协议,如下所示:

CategoryEntity

我尝试从NSUserDefaults的包装器对其进行编码,如下所示:

- (void) encodeWithCoder:(NSCoder*)encoder 
{
    //encode all the values so they can be persisted in NSUserdefaults
    [encoder encodeObject:ID forKey:kIDKey];
    [encoder encodeObject:text forKey:kTextKey];
    [encoder encodeObject:category forKey:kCategoryKey];
    [encoder encodeObject:categoryIdentifierKey forKey:kCategoryIdentifierKey];
}

- (id) initWithCoder:(NSCoder*)decoder 
{
    if (self = [super init]) {

        //decode all values to return an object from NSUserdefaults in the same state as when saved
        [self setID:[decoder decodeObjectForKey:kIDKey]];
        [self setText:[decoder decodeObjectForKey:kTextKey]];
        [self setCategory:[decoder decodeObjectForKey:kCategoryKey]];
        [self setCategoryIdentifierKey:[decoder decodeObjectForKey:kCategoryIdentifierKey]];
    }
    return self;
}

我在想,当我要求序列化SearchEntity时,它会开始序列化'参数'mutableDictionary对象,NSCoder会在字典中包含的CategoryEntities上调用“encode”,它们都将使用正确的编码对象进行响应

但是我得到GDB:在控制台底部中断。

我该如何调试?

我的方法是错误的,我应该在NSData中包装所有级别的编码吗?

聚苯乙烯。我使用包含+ (void) setPreviousSearchParameters:(SearchParameterEntity*) entity { if (entity) { //first encode the entity (implements the NSCoding protocol) then save it NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:entity]; [[self defaults] setObject:encodedObject forKey:kPreviousSearchKey]; [[self defaults] synchronize]; } } + (SearchParameterEntity*) getPreviousSearchParameters { //retrieve the encoded NSData object that was saved, decode and return it SearchParameterEntity *entity = nil; NSData *encodedObject = [[self defaults] objectForKey:kPreviousSearchKey]; if (encodedObject) entity = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject]; return entity; } 的NSArrays的ResultEntity执行完全相同的操作,它编码没有任何问题,所以我想NSMutableDictionary是唯一突出的内容。

3 个答案:

答案 0 :(得分:1)

您发布的代码似乎不正确。我已经对你遗漏的一些细节做了最好的猜测,我从test program得到了一个成功的结果,其中包含了足够的样板代码,以显示它正确编码/解码。

(您可以使用以下命令行从gcc -framework foundation test.m -o test编译它并运行:./test。)

关于你的问题,我该如何调试,我建议采用如下方法:

  • (暂时)将您的代码修改为简单。例如,您可以将parameters属性更改为普通NSString并验证其是否正常工作。
  • 慢慢增加复杂性,一次引入一个新属性,直到错误再次开始。最终,您将缩小数据来源的麻烦。

唉,如果由于应用程序中其他位置的错误管理内存而发生这种情况,那么调试此代码本身可能无法让您随处可见。尝试(手动)验证是否正确处理了为接收编码而收到的每个数据的内存。

如果您已经在使用Core Data,则可以考虑在用户默认值中仅保留对象ID ,并根据该值恢复对象图。 (见:Archiving NSManagedObject with NSCoding)。

答案 1 :(得分:0)

我建议你首先绕过NSMutableArray。让SearchEntity只包含一个CategoryEntity,看它是否有效。

您发布的代码看起来不错,您可能希望为我们提供更详细的背景信息。

对于对象编码,此文件可能有所帮助:DateDetailEntry

答案 2 :(得分:-1)

使用NSKeyedArchiver归档对象的问题是无法编码可变对象。仅限 NSArray NSDictionary NSString NSDate NSNumber 和<的实例strong> NSData (以及它们的一些子类)可以序列化

因此,在您的SearchEntity方法encodeWithCoder:中,您应该尝试从NSMutableDictionary创建NSDictionary,然后编码不可变的方法:

if (parameters) {
    NSDictionary *dict = [NSDictionary dictionaryWithDictionary:parameters];
    [encoder encodeObject:dict forKey:kPreviousSearchEntityKey];
}

同样在initWithCoder:方法中尝试从编码的不可变的那个创建NSMutableDictionary:

NSDictionary *dict = [decoder decodeObjectForKey:kPreviousSearchEntityKey];
     [self setParameters:[NSMutableDictionary dictionaryWithDictionary:dict]];

同时检查parameters字典中的所有obejct是否符合NSCoding协议,并确保所有obejct仅在encodeWithCoder:方法中编码不可变对象。

希望它能解决问题。