具有核心数据和非核心数据源的 UITableView

Posted

技术标签:

【中文标题】具有核心数据和非核心数据源的 UITableView【英文标题】:UITableView with Core Data and non-Core Data sources 【发布时间】:2014-03-29 17:43:22 【问题描述】:

我的 ios Core Data 应用程序存在一些表格视图问题。在应用程序中有一个Master View Controller,它包含一个表视图和一个单独的Creator View Controller,它使用填充的数据创建Core Data 托管对象。

应用程序的当前目标是将文本从 Core Data 对象加载到表格视图单元格中(在 MVC 表格视图中),当点击单元格时,在下方显示一个新单元格(下拉),显示其他信息。

我在-[tableView:cellForRowAtIndexPath:] 中遇到问题,我尝试使用[self.fetchedResultsController objectAtIndexPath:indexPath]; 访问特定的Core Data 对象由于试图实例化额外的子单元格,我无法在正确的索引路径调用正确的对象。如果我有足够的父单元格,我将收到一个不正确的对象作为回报。如果我没有足够的父单元格,我会因为调用超出索引范围的对象而收到 SIGABRT 错误。

我有一个数组,其中包含子单元格的所有索引路径,因此在-[tableView:numberOfRowsInSection:] 中实现了行计数

如果有人有任何建议,或者如果我需要澄清,请告诉我。我不想做一个凌乱的代码转储,所以我展示了我认为是MasterViewController.hfile 的适用部分。 (如果我有太多,也请让我知道)

@interface MasterViewController ()
@property (nonatomic, strong) NSMutableArray *subIndexPaths;
@end

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section


  NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
  NSEntityDescription *entity = [NSEntityDescription entityForName:@"Trinomial" inManagedObjectContext:[self managedObjectContext]];
  [fetchRequest setEntity:entity];
  NSError *error = nil;
  NSInteger count = [_managedObjectContext countForFetchRequest:fetchRequest error:&error];

  if ([self.subIndexPaths count] == 0 || !self.subIndexPaths) 
      return count;


  return (count + [self.subIndexPaths count]);


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
  //Child cell created & returned here
  
  ...
  

  //Create a parent cell & setup/return
  UITableViewCell *parentCell = [tableView dequeueReusableCellWithIdentifier:kParentCell];
  Trinomial *currentTri = [self.fetchedResultsController objectAtIndexPath:indexPath];
  parentCell.textLabel.text = [currentTri retrieveTrinomial];
  return parentCell;


- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
  if ([[[tableView cellForRowAtIndexPath:indexPath] reuseIdentifier] isEqualToString:kParentCell]) 
    if ([self.subIndexPaths containsObject:[NSIndexPath indexPathForRow:(indexPath.row + 1) inSection:indexPath.section]]) 
        //When there is already a child cell present

        [self.subIndexPaths removeObject:newIndexPath];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil] withRowAnimation:UITableViewRowAnimationAutomatic];
        [self.tableView reloadData];

     else 
      //When there isn't a child cell present

      [self.subIndexPaths addObject:newIndexPath];
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
      [self.tableView reloadData];

    

【问题讨论】:

所以从 FRC 创建的单元格可以有另一个单元格与之关联?每个父单元格只有一个孩子(或多个)? 表格视图中每个父单元格只能有一个子单元格。 Fetched Results Controller 返回用于父单元格的对象,是的。 【参考方案1】:

好的,如果你继续,你目前正在尝试做的事情很快就会变得非常混乱。

相反,我会更改您的方法,以便将任何没有孩子的父单元格显示为当前单元格类型,而任何有孩子的父单元格显示为不同的单元格类型 - 其中包括父母和孩子的内容

这样一来,您的索引就不会全乱了。您的部分和行数变得简单。 (顺便说一句,您不应该运行新的 fetch 来获取计数,而是从 FRC 获取)。

唯一稍微复杂的一点是确定行高和使用哪种单元格类型...

【讨论】:

“会变得非常混乱”我认为这是轻描淡写的。 :) 确实,将发生的只是父单元格高度的扩展,而不是创建一个全新的“子单元格”。你说的是这个吗? 是的,完全正确。在自己添加子作为实际单元格时,尝试操纵所有索引路径以从 FRC 中获取数据将是一堆令人讨厌的代码。 是的,这正是我的问题,这是一个很棒的解决方法。非常感谢!

以上是关于具有核心数据和非核心数据源的 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

核心数据 NSFetchedResultsController 和排序

从具有实体之间关系的核心数据中获取数据[重复]

预加载具有多对多关系的核心数据的最佳实践

保存核心数据相关数据并使用具有多个实体的 NSPredicate 和 NSFetchedResultsController 检索

具有关系的核心数据模型

具有本地化字符串的核心数据排序描述符