我有一个UITableView填充了一个标准的NSFetchedResultsController.但是,我想先添加一行或一个部分(最好是行,但是可以真的很好)
现在我可以看到这样做的唯一方法是在处理NSFetchedResultsController的数据处理部分/行时,手动重写所有的NSIndexPath,从而将其看作是在索引0处看到部分,从索引号0开始.似乎是一个非常糟糕的主意,很快会让人困惑,所以我希望避免.
这是一个很好的例子,当你第一次启动它的时候,在官方的Twitter应用程序中,我引导你从朋友列表中添加一些人.
红色部分几乎是我想要实现的,而我认为的黄色部分是同一部分的NSFetchedResultsController的结果(尽管它们的自定义样式可能是一个单独的部分).
解决方法
这是可以以相当干净的方式做的.
我假设你开始使用一个使用Apple的示例代码的标准NSFetchResultsController设置的标准表.
首先你需要两个效用函数:
- (NSIndexPath *)mapIndexPathFromFetchResultsController:(NSIndexPath *)indexPath { if (indexPath.section == 0) indexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]; return indexPath; } - (NSIndexPath *)mapIndexPathToFetchResultsController:(NSIndexPath *)indexPath { if (indexPath.section == 0) indexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]; return indexPath; }
这些应该是相当自我解释的 – 当我们想要使用从获取的结果控制器访问表的索引路径,或者以其他方式删除它时,它们只是帮助者处理添加额外的行.
那么我们需要创建一个额外的单元格:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"MyCellId"; if (indexPath.section == 0 && indexPath.row == 0) { UITableViewCell *cell; cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; cell.selectionStyle = UITableViewCellSelectionStyleGray; cell.textLabel.text = NSLocalizedString(@"Extra cell text",nil); return cell; } UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; } [self configureCell:cell atIndexPath:indexPath]; return cell; }
确保我们配置正确(只有从提取结果控制器的单元格中才能调用configurecell):
// the indexPath parameter here is the one for the table; ie. it's offset from the fetched result controller's indexes - (void)configureCell:(SyncListViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { indexPath = [self mapIndexPathToFetchResultsController:indexPath]; id *obj = [fetchedResultsController objectAtIndexPath:indexPath]; <... perform normal cell setup ...> }
并告诉tableview它存在:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger numberOfRows = 0; if ([[fetchedResultsController sections] count] > 0) { id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; numberOfRows = [sectionInfo numberOfObjects]; } if (section == 0) numberOfRows++; return numberOfRows; }
并回应选择:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; if (indexPath.section == 0 && indexPath.row == 0) { [self doExtraAction]; return; } ... deal with selection for other cells ...
然后重新映射我们从结果控制器获得的任何更新:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; indexPath = [self mapIndexPathFromFetchResultsController:indexPath]; newIndexPath = [self mapIndexPathFromFetchResultsController:newIndexPath]; switch(type) { ... handle as normal ...