自定义部分名称崩溃NSFetchedResultsController [英] Custom Section Name Crashing NSFetchedResultsController

查看:99
本文介绍了自定义部分名称崩溃NSFetchedResultsController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有dueDate属性的managed对象。而不是使用一些丑的日期字符串作为我的UITableView的节头显示我创建了一个名为类别的瞬态属性,并定义如下:

I have a managed object with a dueDate attribute. Instead of displaying using some ugly date string as the section headers of my UITableView I created a transient attribute called "category" and defined it like so:

- (NSString*)category
{
    [self willAccessValueForKey:@"category"];

    NSString* categoryName;
    if ([self isOverdue])
    {
        categoryName = @"Overdue";
    }
    else if ([self.finishedDate != nil])
    {
        categoryName = @"Done";
    }
    else
    {
        categoryName = @"In Progress";
    }

    [self didAccessValueForKey:@"category"];
    return categoryName;
}

这里是NSFetchedResultsController设置:

Here is the NSFetchedResultsController set up:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Task"
                                          inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

NSMutableArray* descriptors = [[NSMutableArray alloc] init];
NSSortDescriptor *dueDateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dueDate"
                                                                  ascending:YES];
[descriptors addObject:dueDateDescriptor];
[dueDateDescriptor release];
[fetchRequest setSortDescriptors:descriptors];

fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"category" cacheName:@"Root"];

该表最初显示正常,显示未完成的项目,其dueDate尚未通过标题为进展。现在,用户可以点击表视图中的一个行,它将新的详细信息视图推送到导航堆栈上。在该新视图中,用户可以点击按钮以指示项目现在是完成。这里是按钮的处理程序(self.task是托管对象):

The table initially displays fine, showing the unfinished items whose dueDate has not passed in a section titled "In Progress". Now, the user can tap a row in the table view which pushes a new details view onto the navigation stack. In this new view the user can tap a button to indicate that the item is now "Done". Here is the handler for the button (self.task is the managed object):

- (void)taskDoneButtonTapped
{
    self.task.finishedDate = [NSDate date];
}

一旦finishedDate属性的值改变但有以下例外:

As soon as the value of the "finishedDate" attribute changes I'm hit with this exception:

2010-03-18 23:29:52.476 MyApp[1637:207] Serious application error.  Exception was caught during Core Data change processing: no section named 'Done' found with userInfo (null)
2010-03-18 23:29:52.477 MyApp[1637:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no section named 'Done' found'

由于新的详细信息视图当前隐藏的UITableView正在尝试更新其行和节,因为NSFetchedResultsController已通知数据集中发生了更改。这里是我的表更新代码(复制自Core Data Recipes示例或CoreBooks示例 - 我不记得哪个):

I've managed to figure out that the UITableView that is currently hidden by the new details view is trying to update its rows and sections because the NSFetchedResultsController was notified that something changed in the data set. Here's my table update code (copied from either the Core Data Recipes sample or the CoreBooks sample -- I can't remember which):

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            // Reloading the section inserts a new row and ensures that titles are updated appropriately.
            [self.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
{
    [self.tableView endUpdates];
}

我在这些函数中放置断点,发现只有controllerWillChange被调用。在任一控制器之前抛出异常:didChangeObject:atIndexPath:forChangeType:newIndex或controller:didChangeSection:atIndex:forChangeType。

I put breakpoints in each of these functions and found that only controllerWillChange is called. The exception is thrown before either controller:didChangeObject:atIndexPath:forChangeType:newIndex or controller:didChangeSection:atIndex:forChangeType are called.

如果我改变我的sectionNameKeyPath只是dueDate,那么一切工作正常。我认为这是因为dueDate属性永远不会改变,而在finishedDate属性更改后读回时类别会不同。

At this point I'm stuck. If I change my sectionNameKeyPath to just "dueDate" then everything works fine. I think that's because the dueDate attribute never changes whereas the category will be different when read back after the finishedDate attribute changes.

请帮助!

UPDATE:

这是我的UITableViewDataSource代码:

Here is my UITableViewDataSource code:

- (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];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    [self configureCell:cell atIndexPath:indexPath];    

    return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];    
    return [sectionInfo name];
}


推荐答案

崩溃是由NSFetchedResultsController不知道完成类别之前的手,因此崩溃。我已经看到这个崩溃了几个其他时间在其他问题,每一个我建议提交雷达票给苹果。这是 NSFetchedResultsController 中的错误。

The crash is being caused by the NSFetchedResultsController not knowing about the "done" category before hand and therefore crashing. I have seen this crash a few other times in other questions and with each one I recommend submitting a radar ticket to Apple. This is a bug in the NSFetchedResultsController.

这篇关于自定义部分名称崩溃NSFetchedResultsController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆