NSFetchedResultsController 不更新 UITableView 的部分索引

Posted

技术标签:

【中文标题】NSFetchedResultsController 不更新 UITableView 的部分索引【英文标题】:NSFetchedResultsController not updating UITableView's section indexes 【发布时间】:2010-01-03 20:55:02 【问题描述】:

我正在使用 NSFetchedResultsController 填充 UITableViewController,结果创建填充部分标题和部分索引的部分。我正在使用以下方法来填充节索引:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView 
    return [fetchedResultsController_ sectionIndexTitles];

现在我遇到了一个问题。当我将新元素添加到与 NSFetchedResultsController 关联的 NSManagedObjectContext 时,新元素将被保存并适当地显示为 UITableView 中的单元格......除了一件事。如果新元素创建了一个新的 SECTION,新的部分索引不会显示在右侧边距中,除非我弹出 UINavigationController 的堆栈并重新加载 UITableViewController。

我已经符合NSFetchedResultsControllerDelegate的接口,手动调用

[self.tableView reloadSectionIndexTitles];

在这两个委托方法的末尾:

controller:didChangeSection... 
controller:didChangeObject...

虽然我可以调试并跟踪方法的执行并查看调用的重新加载调用,但 UITableView 的节索引从不反映节的更改。

再次显示数据 - 新部分在 UITableView 中物理可见(或删除),但部分索引未更新。

我错过了什么吗?

【问题讨论】:

在另一篇文章中,“Tim”提到了以下内容:“在 3.0 SDK 中存在一个已知错误,如果您使用表数据源中的 NSFetchedResultsController。” ***.com/questions/994359/… 但不幸的是,看起来我正在构建“模拟器 - 3.1”。可能还没修好? 【参考方案1】:

看起来这是我们都有的错误。请参阅http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html,了解在我看来是一个相当讨厌的太多代码行的解决方案。我选择了这个:

- (void)viewWillAppear:(BOOL)animated; 
  // This is a dumb hack required by this bug: http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html
  [self.tableView reloadData];

这可能效率低下,但除非您拥有大量数据,否则它可能不会造成任何伤害。而且它只有 1 行代码。所以,当苹果修复他们的 bug 时,你可以轻松将其移除。

【讨论】:

这确实有效。我暂时不使用部分索引,但感谢您的研究。 +1。【参考方案2】:

问题已经两个月了,但我今天遇到了同样的问题。 -reloadSectionIndexTitles 似乎根本不起作用,所以我尝试了一些潜在的黑客攻击,以下哪些对我有用:

@implementation UITableView (JKAdditions)

- (UIView *)indexView 
    Class indexClass = NSClassFromString(@"UITableViewIndex");
    for(UIView *subview in self.subviews)
        if([subview isKindOfClass:indexClass]) return subview;
    
    return nil;


- (void)reloadSectionIndexTitles 
    UIView *indexView = [self indexView];
    [indexView performSelector:@selector(setTitles:) withObject:[self.dataSource sectionIndexTitlesForTableView:self]];
    [indexView setNeedsDisplay];


@end

我真的不知道 Apple 是否会因为这次黑客攻击而拒绝你的应用程序,但这似乎是我唯一的选择。重新加载整个 tableView 根本不是我想要的,因为我必须处理各种动画问题。

希望对遇到同样问题的人有所帮助!

【讨论】:

我不记得了,但这只是让reloadSectionIndexTitles 工作的技巧,不管你在哪里调用它。请注意,这个答案有 3.5 年的历史,可以追溯到 ios 3,此后发生了很大变化。【参考方案3】:

要将已接受的答案与 Alex Reynolds 的答案与延迟相结合,只需调用 reloadData,延迟对应于动画持续时间,即 0.4 或 0.3 秒。

在我的例子中,我将延迟的方法调用粘贴到控制器中:didChangeSection:atIndex:forChangeType:(它是一个核心数据应用程序)。

添加或删除部分时的结果是单元格的标准动画,然后是重新加载数据时更新的索引。

这很丑,让我畏缩,但我对结果没意见。我还向 Apple 提交了一个错误,#8589547。

【讨论】:

【参考方案4】:

尝试将它放在-controllerDidChangeContent: 的末尾,[self.tableView endUpdates] 之后的某个位置。

【讨论】:

感谢您的建议。不幸的是,这对我不起作用。我认为这可能是一个错误,但不确定如何检查或确认。请参阅我添加到原始问题的评论。感谢您的建议。【参考方案5】:

我做的另一件事(对我有用,不能保证它对你有用)是在很短的延迟后执行选择器,例如:

[self performSelector:(@selector(refreshSectionIndex)) withObject:nil afterDelay:0.2];

// ...

- (void) refreshSectionIndex 
    [self.tableView reloadSectionIndexTitles];
    

Core Data 和NSFetchedResultsController 看起来特别糟糕,其中委托表视图更新与获取的数据不同步,导致应用程序崩溃。我真的希望 Apple 正在采取措施修复 4.0 SDK 中这些框架中的错误。真是令人沮丧。

【讨论】:

我在保存一个新元素后尝试了这个。新元素出现。该元素的新部分出现了 - 但不幸的是,新的部分索引标题丢失了。再次感谢您的建议。 如果你想这样做,你不必在你的视图控制器上创建另一个方法,你可以直接在 tableView 上调用它:[tv performSelector:@selector(reloadSectionIndexTitles) withObject:nil afterDelay:0.2];

以上是关于NSFetchedResultsController 不更新 UITableView 的部分索引的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?