这是我的问题概述:
我正在添加(并确认已添加)大约1400个从soap服务加载到CoreDat的关系。关闭应用程序并再次打开它之后,一些关系就会丢失;我只看到他们中的大约800个(虽然它有所不同)。另外,我没有收到任何错误。
现在,更多细节:
我有一个名为User
的对象,其中包含有关用户保存的服务的信息;它看起来像这样:
@interface OosUser : NSManagedObject
+ (OosUser *) userFromSlug: (NSString *) slug;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *slug;
@property (nonatomic, retain) NSMutableSet /* Service */ *services;
- (void) addServicesObject: (Service * )service;
- (void) removeServicesObject: (Service *) service;
@end
@implementation User
@dynamic name;
@dynamic slug;
@dynamic services;
static NSString *fetchPredicate = @"slug = %@";
+ (User *) userFromSlug:(NSString *)slug
{
User *result = [super objectWithPredicate: fetchPredicate, slug];
if (!result) {
result = [super create];
result.slug = slug;
}
return result;
}
@end
在使用数据的代码部分中,关系保存如下:
NSMutableSet *userServices = self.user.services;
for (Service *service in servicesToAdd) {
[self.services addObject: service];
bool contained = false;
for (Service *userService in userServices) {
if ((contained = [userService.slug isEqualToString:service.slug])) {
break;
}
}
if (!contained) {
// [userServices addObject:service];
[self.user addServicesObject: service];
NSError *error = nil;
if (![[service managedObjectContext] save:&error]) {
NSLog(@"Saving failed");
NSLog(@"Error: %@", [error localizedDescription]);
}else {
NSLog(@"Registered service %d: %@", self.services.count, service.slug);
}
}
}
案例是我已经检查过调试器,我可以看到所有1400多个关系都被添加了,但是当应用程序被重置并通过self.user.services恢复时我只能获得大约800个对象。 / p>
为什么会发生这种情况?以前有人有这个吗?
提前致谢。
更新
人们一直在暗示我没有正确使用Core Data,但问题是重启应用后数据丢失了。使用它时绝对没有问题。我使用核心数据是正确的,因为它可以从Apple获得有限的文档和示例。
答案 0 :(得分:11)
NSMutableSet *userServices = self.user.services;
...
[userServices addObject:service];
不能那样做。 self.user.services
不返回可变集。这就是addServicesObject
方法的用途。将第二行更改为:
[self.user addServicesObject:service];
来自Apple文档:
了解点访问器返回的值与
mutableSetValueForKey:
之间的差异非常重要。mutableSetValueForKey:
返回一个可变代理对象。如果改变其内容,它将为关系发出适当的键值观察(KVO)更改通知。点访问器只返回一个集合。如果您操作该代码片段中所示的集合:
[aDepartment.employees addObject:newEmployee]; // do not do this! then KVO change notifications are not emitted and the inverse relationship is not updated correctly.
回想一下,dot只是调用了访问器方法,所以出于同样的原因:
[[aDepartment employees] addObject:newEmployee]; // do not do this, either!
答案 1 :(得分:4)
我遇到了同样的问题,但在设置了反向关系之后,一切都还可以。 我希望这有助于调查这个问题。
答案 2 :(得分:1)
好的,让我们来看看这里的症状。您正在更改上下文中的对象,但是当您重新启动应用程序时,会有一些但不是所有这些更改都存在。
这只能意味着这些更改不会写入持久性存储。由于您看到了一些更改,因此您正在调用save:
方法,但Core Data无法将所有对象识别为需要保存。
这将引导我们如何对所述对象执行更改。您是否以符合KVO标准的方式进行更改?核心数据依赖于KVO来了解发生了哪些变化,因此需要持续进行哪些变更。如果以非KVO方式更改对象,则在检查它们时它们似乎会被更改,但Core Data将不知道这些更改是否存在,因此不会知道它必须保留它们。
我会修改你的代码如下,假设Service
对象具有与User
的反向关系(并且该关系称为user
,并且是1-M的一部分):
[servicesToAdd setValue:self.user forKey:@"user"];
NSError *error = nil;
if (![[service managedObjectContext] save:&error]) {
NSLog(@"Saving failed");
NSLog(@"Error: %@", [error localizedDescription]);
}
这依赖于核心数据将为您设置关系的两端的事实。当然,如果它是多对多的关系,那么代码会略有不同,但我们仍然使用符合KVO的方法进行更改。
[servicesToAdd setValue:self.user forKey:@"user"];
for (Service *service in servicesToAdd) {
[user addServicesObject:service];
}
NSError *error = nil;
if (![[service managedObjectContext] save:&error]) {
NSLog(@"Saving failed");
NSLog(@"Error: %@", [error localizedDescription]);
}
答案 3 :(得分:0)
最后,我通过使用自定义NSPredicate
来解决它,该自定义{{1}}使用我在服务上添加的一个特殊参数来获取服务。
虽然它不理想但它仍然有效。
答案 4 :(得分:0)
我遇到了同样的问题,每次重新启动应用时,与另一个实体的关系都会丢失。我搜索了几个小时。最后我发现了这个问题。
我宣布我的关系为 Transient
,这导致了这个问题。
答案 5 :(得分:0)