Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSFetchedResultsController:如何从实体的多个关系中获取sectionName_Ios_Core Data_Nssortdescriptor_Nsfetchedresultscontroller - Fatal编程技术网

Ios NSFetchedResultsController:如何从实体的多个关系中获取sectionName

Ios NSFetchedResultsController:如何从实体的多个关系中获取sectionName,ios,core-data,nssortdescriptor,nsfetchedresultscontroller,Ios,Core Data,Nssortdescriptor,Nsfetchedresultscontroller,我有这样一个核心数据模型: ParentObject>ChildObject ParentObject和ChildObject都有一个属性levelNumber,如下所示: typedef enum { Primary, Secondary, Tertiary } LevelNumber; 我还有一种方法可以将ParentObject和childObject中的级别号从int转换为string: -(void) levelString { switch(self

我有这样一个核心数据模型:
ParentObject>ChildObject

ParentObject
ChildObject
都有一个属性
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";

   }

}
现在,我在一个表视图中有一个FetchedResultsController,其中列出了
父对象
。 我想在节名中得到的是:

  • 如果
    ParentObject
    Secondary
    treative
    ,则显示该部分 名称为
    二级
    三级
  • 如果
    ParentObject
    Primary
    ,但
    childobject
    中的任何
    Secondary
    treative
    ,则将节名显示为
    Secondary
    treative
  • 如果
    ParentObject
    和所有
    childobject
    都是
    Primary
    ,则将节名显示为
    Primary
如果我只需要查看
ParentObject
levelNumber
,这是非常简单的,如下所示-

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
检查。它是一种新的排序描述符,还是其他什么?

看看苹果的示例代码,该代码解释了如何将日期作为节,您也可以在您的案例中使用它。您在
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
并查看其子对象是否在该保存中。

IMO在父对象模型中有一个单独的属性
sectionLevelNumber
。这可能会对您有所帮助。@Bala如果我理解正确,属性
sectionLevelNumber
本身不会存储任何值,但它的getter实际上会查看
ParentObject
levelNumber
以及所有
ChildObjects
并查看要返回的级别号。这将是一个问题,因为在FRC的第一次获取中,它期望值存储在数据库中,而不是在运行时派生。Mundi已经清楚地解释了这一点,这是一个很好的答案!但是我有一些问题:1)如果“levelNumber”在
keypathsforvaluesafectingsectionidentifier
中注册,是否仍然需要覆盖
setLevelNumber
?2) “@children”中的
@
是打字错误还是故意的?3) 更改ChildObject的levelNumber真的会使相关ParentObject的sectionIdentifier无效吗?也许在ChildObject中重写
setLevelNumber
会很有用。谢谢1) 是的,这是一个很好的做法,没有坏处。2) 打字错误。更正了。3) 原则上你是对的,但我会担心实体之间的相互依赖性。理想情况下,您只能将此功能封装到父实体中。但是,使用当前代码,修改ChildObject的levelNumber不会更新相关ParentObject的sectionIdentifier。因为keypathsforvaluesafectingsectionidentifier中的“children”只影响在“children”关系中添加/删除子对象,而不会修改已经相关的子对象(除非我弄错了)。这是正确的。毕竟,您必须转到子实体。最好覆盖
setLevelNumber
。这不能完全起作用。
请求.排序描述符应使用什么?。如果我只使用
parentObject
levelNumber
。它给出了错误:
CoreData:error:(NSFetchedResultsController)索引2处的获取对象具有无序的节名“2(次要)对象必须按节名排序”
。例如,当所有的
ParentObject
都是
Primary
,但是第二个
ParentObject
ChildObject
中有一个是
Secondary
时,就会发生这种情况。我不能使用
sectionIdentifier
进行排序,因为它是一个临时属性。