Ale*_*lor 10 core-data objective-c nsfetchedresultscontroller ios
我有一个UITableViewController,它由NSFetchedResultsController支持.
我的NSFetchedResultsController根据布尔值将结果放入两个部分.
在后台线程中,更改数据源以便添加或删除行.我有我的后台线程的NSManagedObjectContext正确合并,这种情况适用于大多数情况.数据更改时行会更改,并在带动画的部分之间移动.
但有一种情况是我的应用程序崩溃了EXC_BAD_ACCESS.这种情况是一个部分中的最后一行移动到另一部分.(下面的堆栈跟踪).崩溃发生在objc_msgSend中,但我使用的正常调试提示没有返回任何有用的东西,我只是收到"值无法转换为整数" gdb.
NSFetchedResultsControllerDelegate方法按以下顺序调用:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
// ^ The parameters specify a deletion of the 1st section
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
// ^ The parameters specify a moved row from the 1st section to the 1st section
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
Run Code Online (Sandbox Code Playgroud)
通过StackOverflow,许多遇到类似问题的人正在使用NSArray或NSMutableArray手动备份他们的UITableViewController,他们只是没有在正确的时间更新数据源.在这种情况下,NSFetchedResultsController正在处理返回的行数和节数,并且在[tableView endUpdates]调用时肯定会更新.
有没有人有任何调试技巧,指针或解决方案? 这篇博客文章提示解决创建新部分的类似问题.
如果我不能解决这个问题,我有两个选择:
[tableView reloadData]我修改了Apple示例Core Data应用程序"Locations"以直接使用NSFetchedResultsController并重现该问题. 我已经上传了这个项目的源代码.使用该项目重现该问题.
崩溃有时是关于为该主题创建与其他StackOverflow问题相同的单元格的两个动画.更常见的是,碰撞如上下文所述.
堆栈跟踪:
#0 0x31e0afbc in objc_msgSend ()
#1 0x32c11522 in -[_UITableViewUpdateSupport(Private) _computeRowUpdates] ()
#2 0x32c10510 in -[_UITableViewUpdateSupport initWithTableView:updateItems:oldRowData:newRowData:oldRowRange:newRowRange:context:] ()
#3 0x32c0f99e in -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] ()
#4 0x32c0e66c in -[UITableView endUpdatesWithContext:] ()
#5 0x000088d6 in -[DraftHistoryController controllerDidChangeContent:] (self=0x3f6f1e0, _cmd=0x377ca29c, controller=0x3f716e0) at /Users/ataylor/Documents/Documents/Programming/iPhone/Drafter/Drafter/Drafter/DraftHistoryController.m:323
#6 0x3775a892 in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] ()
Run Code Online (Sandbox Code Playgroud)
我的NSFetchedResultsControllerDelegate方法与Apple示例代码中的方法相同:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
// Reloading the section inserts a new row and ensures that titles are updated appropriately.
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates]; // <---- Crash occurs here
}
Run Code Online (Sandbox Code Playgroud)
相关的UITableViewControllerDelegate方法如下:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
Run Code Online (Sandbox Code Playgroud)
我快速看了一下.您修改后的Locations项目没有崩溃,但它确实生成了核心数据异常.问题在于重新加载控制器中的部分:didChangeObject:.我改变了代码如下,iOS 4.3和iOS 5上的一切看起来都很好(包括章节标题).
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
// other cases here
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6808 次 |
| 最近记录: |