我有两个类: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中,applicationDidEnterBackground
和applicationWillTerminate
同时拨打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
之外的其他数据结构来保存数据,我该如何解决这个问题呢?
答案 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];