如何将 ManagedObjectContext 与线程一起使用
Posted
技术标签:
【中文标题】如何将 ManagedObjectContext 与线程一起使用【英文标题】:How to use ManagedObjectContext with threads 【发布时间】:2010-12-24 16:28:53 【问题描述】:这可能是一个非常简单的应用程序,但我是 Objective-C 的新手(来自 Java),整个内存管理和“EXC_BAD_ACCESS”错误让我心碎。
我有一个普通的 NavigationController iPhone 应用程序,带有核心数据。在 AppDelegate 中创建 NSManagedObjectContext 并将其传递给 RootViewController。直接从主线程中查找视图以填充表格,这似乎工作正常。
该应用程序是某种 RSS 类型的阅读器,因此一旦应用程序启动,我就会触发一个线程来获取新数据并更新视图:
-(void)updateData:(id)sender
UIActivityIndicatorView *activityIndicator =
[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[activityIndicator startAnimating];
UIBarButtonItem *activityItem =
[[UIBarButtonItem alloc] initWithCustomView:activityIndicator];
[activityIndicator release];
self.navigationItem.leftBarButtonItem = activityItem;
[activityItem release];
// Start thread to update the data
[NSThread detachNewThreadSelector:@selector(doUpdateData) toTarget:self withObject:nil];
-(void)doUpdateData
NSLog(@"Update data Thread (in 5 sec.)");
[NSThread sleepForTimeInterval:5];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
DataManager *data = [[DataManager alloc] initWithContext:managedObjectContext];
[data updateData];
[data release];
data=nil;
[self performSelectorOnMainThread:@selector(finishUpdateData) withObject:nil waitUntilDone:NO];
[pool release];
-(void)finishUpdateData
self.navigationItem.leftBarButtonItem = updateBttn;
DataManager *data = [[DataManager alloc] initWithContext:managedObjectContext];
objects = [data getArticles];
[data release];
data=nil;
NSLog(@"Amount of records after update: %d", [objects count]);
[self.tableView reloadData];
问题是这行不通。在 DataManager 中,首先需要检索设置,一旦创建了 NSEntityDescription,我就会得到“EXC_BAD_ACCESS”:
- (NSFetchedResultsController *)fetchedResultsController
// Set up the fetched results controller if needed.
if (fetchedResultsController == nil)
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Setting" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"key" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchLimit:1];
.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
我猜指向 ManagedObjectContext 的指针是错误的,这是由于在不同的线程和内存池中运行所致。那么如果这是问题,你如何创建这样的应用程序),我如何获得对他线程的原始 ManagedObjectContext 格式的引用?
[编辑] 我也尝试过使用
iDomsAppDelegate *appDelegate = (iDomsAppDelegate *)[[UIApplication sharedApplication] delegate];
DataManager *data = [[DataManager alloc] initWithContext:appDelegate.managedObjectContext];
在 doUpdateData 中(正如其他帖子所暗示的那样),但结果相同
【问题讨论】:
【参考方案1】:托管对象上下文不是线程安全的。 Apple's guidelines 表示您必须每个线程有一个单独的 NSManagedObjectContext 实例。
【讨论】:
添加了指向 Apple 指南的链接...除此之外,简短、切中要害且完全正确。以上是关于如何将 ManagedObjectContext 与线程一起使用的主要内容,如果未能解决你的问题,请参考以下文章
将 UITabBarController 与内部 UINavigationControllers 一起使用时如何共享 ManagedObjectContext
如果它是子视图控制器,如何将 AppDelegate 中的 managedObjectContext 传递给正确的视图控制器?
如何使用 managedObjectContext 来使用实体?
将 ManagedObjectContext 传递/注入到视图控制器中