【问题标题】:iOS CoreData / NSFetchedResultsController: Limit Result to 3 per SectioniOS CoreData / NSFetchedResultsController:将每个部分的结果限制为 3
【发布时间】:2015-02-10 07:54:05
【问题描述】:

想象一个新闻应用程序。该应用程序有多个频道,每个频道有 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];
}

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

CoreData:错误:严重的应用程序错误。捕获到异常 在调用期间从 NSFetchedResultsController 的委托 -controllerDidChangeContent:。无效更新:第 3 节中的行数无效。现有节中包含的行数 更新后(3)必须等于包含的行数 更新前的那个部分(3),加减行数 从该部分插入或删除(0 插入,3 删除)和加上 或减去移入或移出该部分的行数(0 移动 入,0 移出)。与 userInfo (null)

知道如何避免这个错误吗?

【问题讨论】:

  • 我认为在这种情况下,您需要获取新闻实体本身而不是频道实体,但使用 NSPredicate。所以基本上像NSPredicate *predicate = [NSPredicate predicateWithFormat: @"channel == %@", channelName]; [fetchRequest2 setPredicate:predicate]; 这样的东西如果你不知道有多少个频道,那么我想你必须执行 2 个获取操作,第一个是获取所有频道,然后我上面提到的第二个获取操作是你设置的地方获取限制为 3
  • 谢谢。但是使用 NSFetchedResultsController 我只能使用一个 NSFetchRequest 吗?
  • 抱歉 Mike,我以前从未使用过 NSFetchResultsController,我倾向于在我的 ViewControllers 或 PersistentStack Core Data 单例中编写所有获取操作:P。我还想提到的第二点是,有一种方法可以有效地重用谓词stackoverflow.com/questions/7708541/… 我认为您应该使用它来替换您的频道名称。
  • 您可以改为修改 UITableView 数据源方法 numberOfRowsInSection 以返回 min(3,section.numberOfObjects)。
  • @pbasdf 我编辑了我的问题并添加了我当前的代码。如您所见,就像您提到的那样。但这也不起作用。

标签: ios uitableview core-data nsfetchedresultscontroller nsfetchrequest


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2011-01-01
    • 2019-07-14
    相关资源
    最近更新 更多