NSFetchedResultsController:如何从实体的to-many关系中获取sectionName

时间:2013-06-29 08:42:59

标签: ios core-data nssortdescriptor nsfetchedresultscontroller

我有一个核心数据模型: ParentObject <--->> ChildObject

ParentObjectChildObject都有一个属性levelNumber

typedef enum {
    Primary,
    Secondary,
    Tertiary
} LevelNumber;

我还有一个方法可以在ParentObject和childObject中将级别号从int转换为string:

-(void) levelString
{
    switch(self.levelNumber)
   {
      case Primary: return @"Primary";
      case Secondary: return @"Secondary";
      case Tertiary: return @"Tertiary";
      default: return @"Error";

   }

}

现在我在tableview中有一个FetchedResultsController,列出了ParentObject。 我想在部分名称中得到的是:

  • 如果ParentObjectSecondaryTertiary,请显示该部分 名称为SecondaryTertiary
  • 如果ParentObjectPrimaryChildObjects中的任何一个为SecondaryTertiary,则将部分名称显示为Secondary }或Tertiary
  • 如果ParentObject和所有ChildObjects都是Primary,请将部分名称显示为Primary

如果我只需要查看levelNumber的{​​{1}},就像下面的内容一样,这非常简单 -

ParentObject

我理解FRC中的限制是SortDescriptor的结果应该以与显示喜欢的顺序相同的顺序返回结果。 如何在此处合并NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ParentObject"]; NSSortDescriptor *levelNumSD = [NSSortDescriptor sortDescriptorWithKey:@"levelNumber" ascending:YES]; request.sortDescriptors = [NSArray arrayWithObjects:levelNumSD, nil]; self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:myContext sectionNameKeyPath:@"levelString" cacheName:nil]; 检查。它会是一种新的SortDescriptor,还是别的什么?

1 个答案:

答案 0 :(得分:2)

看一下Apple的示例代码DateSectionTitles,它解释了如何将日期作为部分,以及您在几乎适用于您的情况。您在titleForSection中管理的字符串的实际显示,但您在数据库中保留了一个“原始”且可排序的属性,称为sectionIdentifier

在您的特定情况下,部分标识符就像levelNumber一样,只需返回所有孩子的最高levelNumber即可计算出来。

模式如下:

-(NSString*)sectionIdentifier {
   [self willAccessValueForKey:@"sectionIdentifier"];
   NSNumber *tmp = [self primitiveSectionIdentifier];
   [self didAccessValueForKey:@"sectionIdentifier"];

   if (!tmp) {
      NSNumber *childrenMax = [self valueForKeyPath:@"@max.children.levelNumber"];
      tmp = childrenMax.intValue > self.levelNumber.intValue ?
            childrenMax : self.levelNumber;
      [self setPrimitiveSectionIdentifier:tmp];
   }

   return tmp;
}

如果实体发生变化,请不要忘记重置它。

-(void)setLevelNumber:(NSNumber)newNumber {
   [self willChangeValueForKey:@"levelNumber"];
   [self setPrimitiveLevelNumber:newNumber];
   [self willChangeValueForKey:@"levelNumber"];

   [self setPrimitiveSectionIdentifier:nil];
}

最后,确保在相关数据发生变化时无效:

+(NSSet*) keyPathsForValuesAffectingSectionIdentifier {
   return [NSSet setWithObject:@"levelNumber"];
}

要监控所有孩子的levelNumber中的更改,请让家长听取NSManagedObjectContextDidSaveNotification并查看其中的任何子女是否在该保存中。