问题描述
我有两个类:Profile 和 Config.Profile 包含一个 NSSet 的 Config 对象.Profile 和 Config 都是 NSManagedObject
子类.
I have two classes: Profile and Config. A Profile contains an NSSet of Config objects. Both Profile and Config are NSManagedObject
subclasses.
@interface Profile : NSManagedObject
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *configs;
- (void)print;
@end
这里是配置类
@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
保存方法并且该方法运行良好且没有错误.只要我不杀死应用程序,一切都会按预期运行.
The dictionary myDict has NSString
*keys and values. Now when I make any changes to myDict, I call the NSManagedObject
save method and that works fine with no errors. As long as I do not kill the app, everything behaves as expected.
但是当我强制终止应用程序(在 Xcode 中或通过双击主页按钮并在底部的按钮行中终止它)然后重新启动应用程序时,myDict 中的数据恢复到之前的数据,即新数据实际上并未保存.它似乎是在我杀死应用程序之前保存的.
But when I force kill the app (either in Xcode or by double pressing the home button and killing it in the row of buttons at the bottom) and then restart the app, the data in myDict reverts to what was there before, ie the new data was not actually saved. It only appeared to be saved before I killed the app.
myDict 在 xcdatamodeld 文件中列为可转换.我在没有指定任何 NSTransformer
类的情况下尝试了它.我还尝试指定一个转换器类 MyDictTransformer,并在 Config 中添加了以下代码:
myDict is listed as Transformable inside the xcdatamodeld file. I tried it without specifying any NSTransformer
class. I also tried it specifying a transformer class MyDictTransformer, and in Config I added this code:
在 Config.h 中:
In Config.h:
@interface MyDictTransformer : NSValueTransformer
@end
在 Config.m 中:
In 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 的顶部我有这个:
Also at top of Config.m I have this:
//
// 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:
Also in AppDelegate, in both applicationDidEnterBackground
and applicationWillTerminate
I call 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 中.
No matter what I have tried, it simply does not save the dictionary in Config. It saves any other changes in things like config.name but not in config.myDict.
A) 我做错了什么?B) 我该如何解决这个问题,即使我必须使用除 NSMutableDictionary
之外的其他数据结构来保存数据?
A) What am I doing wrong?B) How can I fix this, even if I have to use some other data structure than an NSMutableDictionary
to save the data?
推荐答案
您已将 myDict
声明为 NSMutableDictionary
,这是一个很大的危险信号.
You've declared myDict
as an NSMutableDictionary
which is a big red flag.
托管对象属性应该永远是可变类型
Managed object attributes should never be a mutable type
很有可能,您正在使用 myDict
类似的东西:
Chances are, you're using myDict
something like this:
someConfig.myDict[@"someKey"] = @"someValue";
[context save:&error];
问题是,您没有调用 someConfig
的 setter 方法,因此您没有做任何事情来通知它某个属性已更改.即使您调用 save:
,上下文也不会打扰保存未更改的对象.
The problem is, you're not calling a setter method of someConfig
so you've done nothing to inform it that an attribute has been changed. And even though you're calling save:
, the context doesn't bother saving unchanged objects.
严格来说,每次更改 myDict
时,您可能可以避免调用 [someConfig didChangeValueForKey:@"myDict"]
.不过我不推荐它,因为它很容易忘记并且容易出错.
Strictly speaking, you could probably get away with calling [someConfig didChangeValueForKey:@"myDict"]
every time you change myDict
. I wouldn't recommend it though because it's easy to forget and error prone.
最好将 myDict
声明为非可变的并像这样使用它:
It would better to declare myDict
as non-mutable and use it like this:
@property (nonatomic, retain) NSDictionary *myDict;
...
NSMutableDictionary *updatedDict = [someConfig.myDict mutableCopy];
updatedDict[@"someKey"] = @"someValue";
someConfig.myDict = [updatedDict copy];
[context save:&error];
这篇关于核心数据不保存可转换的 NSMutableDictionary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!