Core Data 支持带有索引的 UITableView

发布于 2024-08-08 15:03:54 字数 1384 浏览 5 评论 0原文

我正在尝试实现一个支持索引的核心数据 UITableView (例如:出现在侧面的字符以及与之相关的节标题)。在不使用 Core Data 的情况下实现这一点完全没有问题:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;

我在不使用索引的情况下实现由 Core Data 支持的 UITableView 也没有问题。

我想弄清楚的是如何优雅地将两者结合起来?显然,一旦您索引并重新划分内容,您就不能再使用标准 NSFetchedResultsController 来检索给定索引路径中的内容。因此,我将索引字母存储在 NSArray 中,将索引内容存储在 NSDictionary 中。这一切对于显示来说都工作得很好,但是在添加和删除行时我有一些真正的头痛,特别是如何正确实现这些方法:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;

因为它返回的索引路径与核心数据中的索引路径没有相关性。当用户添加一行时,我通过简单地重建索引 NSArray 和 NSDictionary 来添加工作,但当他们删除一行时,执行相同的操作会导致整个应用程序崩溃。

我在这里缺少一个简单的模式/示例来使所有这些正常工作吗?

编辑:只是为了澄清,我知道 NSFetchedResultsController 是开箱即用的,但我想要的是复制像联系人应用程序这样的功能,其中索引是人名的第一个字母。

I am trying to implement a Core Data backed UITableView that supports indexing (eg: the characters that appear down the side, and the section headers that go with them). I have no problems at all implementing this without Core Data using:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;

I also have no problem implementing a UITableView that is backed by Core Data without using the indexing.

What I am trying to figure out is how to elegantly combine the two? Obviously once you index and re-section content, you can no longer use the standard NSFetchedResultsController to retrieve things at a given index path. So I am storing my index letters in an NSArray and my indexed content in an NSDictionary. This all works fine for display, but I have some real headaches when it comes to adding and deleting rows, specifically how to properly implement these methods:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;

Because the index paths it's returning me have no correlation with the ones in core data. I got add working by simply rebuilding my index NSArray and NSDictionary when the user adds a row, but doing the same when they delete one crashes the whole application.

Is there a simple pattern/example I'm missing here to make all this work properly?

Edit: Just to clarify I know that the NSFetchedResultsController does this out of the box, but what I want is to replicate the functionality like the Contacts app, where the index is the first letter of the first name of the person.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓝眸 2024-08-15 15:03:55

您应该使用 CoreData NSFetchedResultsController 来获取您的部分/索引。
您可以在获取请求中指定节键(我认为它必须与第一个排序键匹配):

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"name" // this key defines the sort
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext
sectionNameKeyPath:@"name" // this key defines the sections
cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

然后,您可以像这样获取节名称:

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

节索引在这里:

id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
[sectionInfo indexTitle]; // this is the index

对内容的更改仅表明该表需要更新:

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

更新
这仅适用于索引和快速索引滚动,不适用于节标题。
请参阅此答案 “如何使用第一个字符作为节名称”,了解有关如何实现节标题和索引的第一个字母的更多信息和详细信息。

You should use your CoreData NSFetchedResultsController to get your sections/indexes.
You can specify the section key in the fetch request (I think it has to match the first sort key):

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"name" // this key defines the sort
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext
sectionNameKeyPath:@"name" // this key defines the sections
cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

Then, you can get the section names like this:

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

And the section indexes are here:

id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
[sectionInfo indexTitle]; // this is the index

Changes to the content just indicate that the table needs to be updated:

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

UPDATE
This only works for the index and fast index scrolling, not for the section headers.
See this answer to "How to use the first character as a section name" for more information and details on how to implement first letters for section headers as well as the index.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文