需要帮助设置后台托管对象上下文。在 FRC controllerDidChangeContent 上获取异常
Posted
技术标签:
【中文标题】需要帮助设置后台托管对象上下文。在 FRC controllerDidChangeContent 上获取异常【英文标题】:Need help setting up background managed object context. Getting exception on FRC controllerDidChangeContent 【发布时间】:2014-03-02 15:03:26 【问题描述】:我有一个包含两个托管对象上下文的应用:
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) NSManagedObjectContext *backgroundContext;
我的一个视图控制器是一个UITableView
控制器,它响应NSFetchedResultsControllerDelegate
。当我(从远程 Web 服务)获取对象时,我想在后台线程上处理数据,将更改合并到我的主 managedObjectContext
并更新 UI。
在我当前的设置下,当我尝试获取新对象时出现以下异常。
CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil with userInfo (null)
此异常在以下位置引发:
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
[self.tableView endUpdates];
我的托管对象上下文是在一个名为 AppController
的单例类中创建的。目前看起来是这样的:
- (id)init
self = [super init];
if (self)
sharedInstance = self;
// Registers NSManagedObjectContextDidSaveNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext];
return self;
- (void)mergeChanges:(NSNotification *)notification
//should tell the main thread moc to run on the main thread, and merge in the changes there
[self.managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];
- (void)saveContext
NSError *childError = nil;
[self.backgroundContext save:&childError];
[self.managedObjectContext performBlock:^
NSError *parentError = nil;
[self.managedObjectContext save:&parentError];
];
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
if (_managedObjectContext != nil)
return _managedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
self.backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType];
self.backgroundContext.parentContext = self.managedObjectContext;
return _managedObjectContext;
对我缺少什么或做错了什么有任何想法?
【问题讨论】:
【参考方案1】:我认为你必须在你的后台进程中创建你的 backgroundContext。
并且需要监听backgroundContext发送的通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:self.backgroundContext];
在我的例子中,runupdate 在后台进程中运行:
- (void) runUpdate
NSManagedObjectContext *managedContext = [[NSManagedObjectContext alloc] init];
managedContext.persistentStoreCoordinator = ...;
[updateController registerBackgroundMoc:managedContext];
//do all update stuff
NSError *error;
if (![managedContext save: &error]
...
[updateController unregisterBackgroundMoc:managedContext];
在我的 updateController 中,我执行了以下操作:
- (void) registerBackgroundMoc: (NSManagedObjectContext *) updateMoc
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(mergeChanges:) name: NSManagedObjectContextDidSaveNotification object: updateMoc];
- (void) unregisterBackgroundMoc: (NSManagedObjectContext *) updateMoc
[[NSNotificationCenter defaultCenter] removeObserver: self name: NSManagedObjectContextDidSaveNotification object: updateMoc];
【讨论】:
以上是关于需要帮助设置后台托管对象上下文。在 FRC controllerDidChangeContent 上获取异常的主要内容,如果未能解决你的问题,请参考以下文章