我需要一些帮助来使用Core Data with GCD中的对象;我似乎得到NSManagedObjects,即使我访问他们的属性,也没有出现在主线程中 . 会感激一些帮助 .
这就是我正在做的事情:在启动时,我需要从Core Data DB加载人员列表,在后台进行一些自定义处理,然后重新加载表以显示名称 . 我通过仅将objectID传递到GCD队列来遵循Core Data多线程的准则 . 但是当我在主线程上重新加载tableview时,我从未看到为联系人显示的名称(或其他属性),并且仔细观察,NSManagedObjects结果是主线程上的错误,即使我访问了各种属性的cellForRowAtIndexPath . 当我NSLog时,名称属性在后台线程中可见;并且它也在cellForRowAtIndexPath中的NSLogs中的主线程上正确显示 . 但无论我做什么,它们都不会在tableView中显示 . 我尝试使用点表示法访问name属性,以及valueForKey,但都没有工作 .
这是我的代码......它是从FRC初始化程序调用的:
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil)
{
return __fetchedResultsController;
}
__fetchedResultsController = [self newFetchedResultsControllerWithSearch:nil]; // creates a new FRC
[self filterAllContactsIntoDictionary: __fetchedResultsController];
return [[__fetchedResultsController retain] autorelease];
}
- (void) filterAllContactsIntoDictionary: (NSFetchedResultsController *) frc
{
NSArray *fetchedIDs = [[frc fetchedObjects] valueForKey:@"objectID"];
NSArray *fetched = [frc fetchedObjects];
if (filterMainQueue == nil) {
filterMainQueue = dispatch_queue_create("com.queue.FilterMainQueue", NULL);
}
dispatch_async(self.filterMainQueue, ^{
NSManagedObjectContext *backgroundContext = [[[NSManagedObjectContext alloc] init] autorelease];
[backgroundContext setPersistentStoreCoordinator:[[self.fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
NSMutableArray *backgroundObjects = [[NSMutableArray alloc] initWithCapacity: fetchedIDs.count];
// load the NSManagedObjects in this background context
for (NSManagedObjectID *personID in fetchedIDs)
{
Person *personInContext = (Person *) [backgroundContext objectWithID: personID];
[backgroundObjects addObject:personInContext];
}
[self internal_filterFetchedContacts: backgroundObjects]; // loads contacts into custom buckets
// done loading contacts into character buckets ... reload tableview on main thread before moving on
dispatch_async(dispatch_get_main_queue(), ^{
CGPoint savedOffset = [self.tableView contentOffset];
[self.tableView reloadData];
[self.tableView setContentOffset:savedOffset];
});
});
}
我在这做错了什么?有没有其他方法可以显式地使Person对象在主线程上触发它们的错误?或者我是否对GCD队列和核心数据做错了,我不知道?谢谢 .
3 回答
为什么不采取简单的路线,因为你没有保存新的东西?不是为后台线程创建额外的上下文并使用ID,而是在锁定后使用后台线程中的主
managedObjectContext
.例如:
当我用
performSelectorInBackground
调用方法时,这对我有用,所以我猜它也适用于GCD调度 .好吧,
mergeChangesFromContextDidSaveNotification:
是你的朋友 . 你需要在主线程上告诉MOC其他地方有变化 . 这样就可以了 .Here's Apple's documentation . 从那里引用:
编辑:删除原始答案,OP不在后台获取
我仔细查看了您的代码,看起来您没有做任何会改变数据和/或影响主线程上下文的事情 .
主线程上有
fetchedResultsController
. 据推测,这是有效的,你的表填充了数据 . 这是真的?当调用
filterAllContentsIntoDictionary
时,将fetchedResultsController
的当前objectID的数组传递给后台线程并对它们进行一些处理(可能根据某些条件对它们进行过滤),但是您没有更改数据并保存backgroundContext
.internalFilterFetchedContents
是一个黑盒子 . 不知道你打算做什么,很难说为什么它不起作用 .完成后,在主线程上重新加载表 .
您尚未对商店,上下文或fetchedResultsController进行任何更改,因此该表显示了之前执行的相同数据 . 缺少的细节将进一步帮助:
tableView
是否显示fetchedResultsController
中的正确数据?如果没有,很可能你唯一的问题是处理tableView
委托和dataSource方法,其余部分并不真正相关 .你打算在
filterAllContentsIntoDictionary
和internalFilterFetchedContents
发生什么?如果您的意图是过滤
fetchedResultsController
所显示的数据,不确定您是否需要在后台执行任何操作 . 如果您修改fetchRequest并再次执行performFetch
,您的表将根据新结果重新加载 .我需要更多帮助,请回答我的问题,在帖子中添加更多相关代码,如果我遗漏了问题以及你想要完成什么,请告诉我 .
祝好运!