Core Data不保存可转换的NSMutableDictionary

时间:2014-03-05 23:27:21

标签: ios objective-c core-data nsmanagedobjectcontext

我有两个类:Profile和Config。配置文件包含NSSet的Config对象。 Profile和Config都是NSManagedObject子类。

@interface Profile : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *configs;

- (void)print;

@end

这是Config类

@interface Config : NSManagedObject

@property (nonatomic, retain) NSString * otherdata;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSMutableDictionary *myDict;
@property (nonatomic, retain) Profile *profile;

- (void)print;

@end

字典myDict有NSString *键和值。现在,当我对myDict进行任何更改时,我调用NSManagedObject保存方法,并且没有错误,工作正常。只要我不杀死应用程序,一切都按预期运行。

但是当我强制杀死应用程序时(无论是在Xcode中还是双击主页按钮并在底部的按钮行中将其杀死)然后重新启动应用程序,myDict中的数据将恢复为之前的状态,即新数据实际上没有保存。它只是在我杀死应用程序之前才被保存。

myDict在xcdatamodeld文件中列为Transformable。我在没有指定任何NSTransformer类的情况下尝试了它。我也尝试过指定变换器类MyDictTransformer,在Config中我添加了这段代码:

在Config.h中:

@interface MyDictTransformer : NSValueTransformer

@end

在Config.m中:

@implementation MyDictTransformer

+ (Class)transformedValueClass
{
    return [NSMutableDictionary class];
}

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    return [NSKeyedArchiver archivedDataWithRootObject:value];
}

- (id)reverseTransformedValue:(id)value
{
    return [NSKeyedUnarchiver unarchiveObjectWithData:value];
}

@end

同样在Config.m的顶部,我有这个:

//
// from: http://stackoverflow.com/questions/4089352/core-data-not-updating-a-transformable-attribute
//

+ (void)initialize {
    if (self == [Config class]) {
        MyDictTransformer *transformer = [[MyDictTransformer alloc] init];
        [NSValueTransformer setValueTransformer:transformer forName:@"MyDictTransformer"];
    }
}

同样在AppDelegate中,applicationDidEnterBackgroundapplicationWillTerminate同时拨打saveContext:

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil)
    {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
        {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }
}

无论我尝试过什么,它都不会在Config中保存字典。它会保存config.name之类的任何其他更改,但不会保存在config.myDict中。

A)我做错了什么? B)即使我必须使用除NSMutableDictionary之外的其他数据结构来保存数据,我该如何解决这个问题呢?

1 个答案:

答案 0 :(得分:20)

您已将myDict声明为NSMutableDictionary,这是一个大红旗。

托管对象属性从不是一种可变类型

有可能,你正在使用myDict这样的东西:

someConfig.myDict[@"someKey"] = @"someValue";
[context save:&error];

问题是,你没有调用someConfig的setter方法,因此你没有做任何事情来通知它属性已被更改。即使你正在调用save:,上下文也不会为保存未更改的对象而烦恼。

严格来说,每次更改[someConfig didChangeValueForKey:@"myDict"]时,您都可能会致电myDict。我不推荐它,因为它很容易忘记并且容易出错。

最好将myDict声明为不可变,并使用它:

@property (nonatomic, retain) NSDictionary *myDict;
...
NSMutableDictionary *updatedDict = [someConfig.myDict mutableCopy];
updatedDict[@"someKey"] = @"someValue";
someConfig.myDict = [updatedDict copy];
[context save:&error];