我正在尝试在完成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]);
}
}
}
}
我无法确定问题在哪里,上下文不是零,我没有得到任何错误。如果我重新启动应用程序,数据就在那里。
答案 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];