我有这样一个核心数据模型:ParentObject <--->> ChildObjectParentObjectChildObject都具有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";

   }

}

现在,我在一个列出ParentObject的表视图中有一个FetchedResultsController。
我想在部分名称中得到的是:
  • 如果ParentObjectSecondaryTertiary,请显示
    名称为SecondaryTertiary
  • 如果ParentObjectPrimary,但是任何ChildObjectsSecondaryTertiary,则将段名称显示为SecondaryTertiary
  • 如果ParentObject和所有ChildObjectsPrimary,则将段名称显示为Primary

  • 如果我只需要查看levelNumberParentObject,则非常简单,类似于以下内容:
    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];
    

    我知道FRC中的限制是SortDescriptor的结果应按希望显示的顺序返回结果。
    我也如何在这里合并ChildObject检查。它是新型的SortDescriptor还是其他?

    最佳答案

    看一下苹果的示例代码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并查看该子项中是否有其子项。

    10-05 20:06