在应用关闭之前,Core Data不会保存数据

时间:2013-12-22 23:12:26

标签: ios objective-c core-data nsmanagedobjectcontext

我正在尝试在完成Web请求后将数据保存到核心数据中。 在AppDelegate我有我的背景。在下面的代码中获取上下文:

- (NSManagedObjectContext *)contex {
    @synchronized(self) {
        if (_contex == nil) {
            _contex = [[NSManagedObjectContext alloc] init];
            [_contex setPersistentStoreCoordinator:self.persistentStoreCoordinator];
        }
        return _contex;
    }
}

与Apple指南一样,我有一个与多个上下文共享的持久性商店协调数据。

这是我从web获取数据,获取上下文并调用方法的代码,用于将新值保存到核心数据中。

NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error) {
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
            UIImage *image;
            if (!error) {
                NSData *imageData = [NSData dataWithContentsOfURL:localFile];
                image = [UIImage imageWithData:imageData];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"thumbnailIsSetted" object:self userInfo:@{@"image": image,
                                                                                                                           @"PhotoUrl": photo.url}];
                    @synchronized(self) {
                        NSManagedObjectContext *context = [(SocialMapAppDelegate *)[[UIApplication sharedApplication] delegate] contex];
                        [Photo addThumbnailData:imageData toPicture:photo.url fromContext:context];
                    }
                });
            } else {
                //if we get an error, we send the default icon
                image = [UIImage imageNamed:@"Photo-thumbnail"];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"thumbnailIsSetted" object:self userInfo:@{@"cached image": image,
                                                                                                                           @"PhotoUrl": photo.url}];
                });
            }
        }];
        [task resume]; //we resume the task in case it is souspended
    }];

这是我用来将数据保存到核心数据的方法:

+ (void)addThumbnailData:(NSData *)data toPicture:(NSString *)pictureUrl fromContext:(NSManagedObjectContext *)context 
{
    if (pictureUrl && context) {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
        request.predicate = [NSPredicate predicateWithFormat:@"url == %@",pictureUrl];
        NSError *error = nil;
        NSArray *matches = [context executeFetchRequest:request error:&error];
        if ([matches count] == 1) {
            Photo *photo = [matches lastObject];
            photo.thumbnailData = data;

            if (![context save:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            }
        }
    }
}

我无法确定问题在哪里,上下文不是零,我没有得到任何错误。如果我重新启动应用程序,数据就在那里。

3 个答案:

答案 0 :(得分:1)

除非您在应用程序中使用多线程设计,否则我不建议使用多个上下文。我建议将应用程序剥离到一个上下文,以避免传递通知。它根本不需要99%的时间。

此外,如果您使用父/子上下文,我不建议重新使用子上下文。它们应该是暂时的;用于单个任务然后扔掉。原因是数据变化只流向一个方向;起来。如果你改变了一个孩子的某些东西,它就不会被推到任何兄弟姐妹身上。此外,儿童情境变得陈旧。如果您在主要上下文中进行更改,则所有子项都将过时。

您的UI应该在整个应用程序中使用单个NSManagedObjectContext。这很可能会解决您的问题。

答案 1 :(得分:0)

代码看起来没问题...保存将上下文的内容保存到磁盘上。刷新其他上下文,你必须听取ContextDidSave通知并合并数据

首先观察:

...
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(mergeChanges:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:managedObjectContext];            
...

然后合并

- (void)mergeChanges:(NSNotification *)notification {
    // Merge changes into the main context on the main thread
    [self.mainManagedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
    withObject:notification
 waitUntilDone:YES];
}

答案 2 :(得分:0)

我解决了,问题发生在我可视化并在该类中查询数据的类中,而不是通过这种方式从appDelegate获取上下文:

[(SocialMapAppDelegate *)[[UIApplication sharedApplication] delegate] contex];

我做了这个

[[SocialMapAppDelegate alloc] init].contex

通过这种方式,我可以简单地创建另一个上下文和另一个商店,这是完全错误的,所以我只需用上面的代码替换就可以解决

    [(SocialMapAppDelegate *)[[UIApplication sharedApplication] delegate] contex];