cha*_*bag 5 core-data nssortdescriptor nsfetchedresultscontroller ios
我的 iOS 应用程序有一个视图控制器,用于显示收件箱项目列表。NSFetchedResultsController这些收件箱项目是核心数据数据库中的实体,并且通过使用主线程管理上下文( )在视图控制器中管理列表NSMainQueueConcurrencyType。
除了 之外NSFetchedResultsController,对实体的所有访问都仅限于在具有私有上下文的专用 GCD 调度队列上运行的代码。因此,在实体中设置属性值以及读取这些实体属性值都发生在这个专用的 GCD 队列和上下文上。
视图控制器监视NSFetchedResultsController主线程上下文中的变化。更改发生在后台专用队列和上下文上。代码监视NSManagedObjectContextDidSaveNotification通知,当后台线程更新属性值时,这些更改将被推送到主线程上下文中。
NSFetchedResultsController 设置为对两个排序描述符进行排序,“sortScore”和“date”(现在只有其中一个正在更新,“date”,因此每个托管对象实例都具有相同的“sortScore”,不是吗?影响排序。)
当“日期”发生更改时,会NSFetchedResultsController注意到它并发布更改,但它将其发布为“更新”而不是“移动”,因此排序不会根据排序描述符和“ date”的更新方式使得新值应该落在排序中的其他位置。
经过几个小时的工作和跟踪NSManagedObjectContextDidSaveNotification以及所有其他可能发生故障的点之后,我对为什么获取的结果控制器发送“更新”更改而不是“移动”更改感到茫然。
此应用程序使用 Robbie Hanson XMPPFramework 的旧分叉版本来管理核心数据(以防熟悉)。
(使问题更加复杂的是,昨晚它确实起作用了,并且移动是在一次运行中发生的。我删除了该应用程序并从全新安装开始,它开始工作。但后续运行不起作用并删除该应用程序以启动fresh 并没有解决这个问题,因此 start fresh 的效果可能是巧合。)
我使用了日志记录和断点来显示获取的结果控制器正在发送“更新”而不是“移动”。
这是代码。
设置并进行初始设置,NSFetchedResultsController并在视图控制器的 init 内部调用此 create 方法。
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
- (NSFetchedResultsController *)createFetchedResultsControllerUsingStorage:(XMPPCoreDataStorage *)storage entityName:(NSString *)entityName
{
NSManagedObjectContext *context = [storage mainThreadManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:entityName];
NSSortDescriptor *sortDescriptorScore = [[NSSortDescriptor alloc] initWithKey:@"sortScore" ascending:NO];
NSSortDescriptor *sortDescriptorDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptorScore, sortDescriptorDate, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
[controller setDelegate:self];
[self updateResultsDataSetForController:controller];
return controller;
}
- (BOOL)updateResultsDataSetForController:(NSFetchedResultsController *)controller
{
NSError *error;
BOOL success = [controller performFetch:&error];
if (nil != error) {
NSLog(@"Error fetching inbox items for the inbox view controller. Error = %@", error);
}
return success;
}
Run Code Online (Sandbox Code Playgroud)
处理更改的代码NSFetchedResultsControllerDelegate基本上是从 Apple 文档复制并粘贴的
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.conversationsTable beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.conversationsTable insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.conversationsTable deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.conversationsTable;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate: {
MyAppInboxCell *cell = [tableView cellForRowAtIndexPath:indexPath];
MyAppXMPPInboxBaseMember *inboxItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
MyAppConversation *conversation = [inboxItem conversation];
[cell configureCell:conversation];
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
453 次 |
| 最近记录: |