iOS CoreData / NSFetchedResultsController:将结果限制为每节3个

时间:2015-02-10 07:54:06

标签: ios uitableview core-data nsfetchedresultscontroller nsfetchrequest

想象一下新闻应用。该应用程序有多个频道,每个频道有x个新闻。 第一个ViewController是一个UITableViewController,它将所有Channels显示为Sections和max。每个频道/部分3个新闻。

我使用NSFetchedResultsController。我怎样才能实现NSFetchedResultsController每节获取3个新闻?

将NSFetchRequest中的fetchLimit设置为3会将整个结果限制为3(= 1行包含3行)。

有什么想法吗?

修改

目前我使用此代码:
UITableViewDataSource 东西(NUMBER_OF_ITEMS_PER_CHANNEL = 3):

- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
    return [self.fetchedResultsController.sections count];
}

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    id<NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
    NSInteger numberOfRows = [sectionInfo numberOfObjects];
    if (numberOfRows > NUMBER_OF_ITEMS_PER_CHANNEL) {
        numberOfRows = NUMBER_OF_ITEMS_PER_CHANNEL;
    }
    return numberOfRows;

}

NSFetchedResultsControllerDelegate 东西:

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

- (void)controller:(NSFetchedResultsController*)controller
    didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
             atIndex:(NSUInteger)sectionIndex
       forChangeType:(NSFetchedResultsChangeType)type
{
    UITableView* tableView = self.tableView;

    switch (type) {
    case NSFetchedResultsChangeInsert:
        [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;
    default:
        break;
    }
}

- (void)controller:(NSFetchedResultsController*)controller
    didChangeObject:(id)anObject
        atIndexPath:(NSIndexPath*)theIndexPath
      forChangeType:(NSFetchedResultsChangeType)type
       newIndexPath:(NSIndexPath*)newIndexPath
{
    UITableView* tableView = self.tableView;

    switch (type) {
    case NSFetchedResultsChangeInsert:
        if (newIndexPath.row < NUMBER_OF_ITEMS_PER_CHANNEL) {
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            id<NSFetchedResultsSectionInfo> sectionInfo = [controller sections][newIndexPath.section];
            NSInteger numberOfRowsInSection = [sectionInfo numberOfObjects];
            if (numberOfRowsInSection > NUMBER_OF_ITEMS_PER_CHANNEL) {
                [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:NUMBER_OF_ITEMS_PER_CHANNEL inSection:newIndexPath.section]] withRowAnimation:UITableViewRowAnimationFade];
            }
        }
        break;

    case NSFetchedResultsChangeDelete:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:theIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self fetchedResultsController:controller configureCell:[tableView cellForRowAtIndexPath:theIndexPath] atIndexPath:theIndexPath];
        break;

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:theIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    }
}

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

但是当有新的新闻可用时(控制器:didChangeObject ....用type = NSFetchedResultsChangeInsert调用)我得到这样的错误:

  

CoreData:错误:严重的应用程序错误。抓住了一个例外   在调用期间来自NSFetchedResultsController的委托   -controllerDidChangeContent :.无效更新:第3节中的行数无效。现有部分中包含的行数   更新后(3)必须等于包含的行数   更新前的那一节(3),加上或减去行数   从该部分插入或删除(0插入,3删除)和加号   或减去移入或移出该部分的行数(0移动   in,0搬出去了)。 with userInfo(null)

知道如何避免此错误吗?

1 个答案:

答案 0 :(得分:0)

我为我的问题找到了解决方法(这避免了CoreData错误)。但是我没有找到如何获得3个新闻PER频道的解决方案(仍然对那个频道感兴趣......)。

如果你们中的一个有同样的问题 - 这里我的解决方法:
而不是删除部分的最后一行(第三行)并插入一个新的部分,我只需像这样更新单元格:

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

...

    switch (type) {
    case NSFetchedResultsChangeInsert:
        if (newIndexPath.row < self.numberOfNewsItemsToFetch) {
            id<NSFetchedResultsSectionInfo> sectionInfo = [controller sections][newIndexPath.section];
            NSInteger numberOfRowsInSection = [sectionInfo numberOfObjects];
            if (numberOfRowsInSection >= self.numberOfNewsItemsToFetch) {
                NSIndexPath* indexPath = nil;
                for (NSUInteger i = newIndexPath.row; i < self.numberOfNewsItemsToFetch; i++) {
                    indexPath = [NSIndexPath indexPathForRow:i inSection:newIndexPath.section];
                    [self fetchedResultsController:controller configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
                }
            }
            else {
                [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            }
        }
        break;
...
    }
}