关闭应用后,某些CoreData关系会丢失

时间:2011-12-21 09:08:33

标签: iphone objective-c core-data persistence

这是我的问题概述:

我正在添加(并确认已添加)大约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获得有限的文档和示例。

6 个答案:

答案 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 ,这导致了这个问题。

enter image description here

答案 5 :(得分:0)

对我来说,问题是反向关系

有我的模特

enter image description here

所有人都有这样的反向关系:

enter image description here

enter image description here