NSFetchedResultsController: Cómo get sectionName de la relación entre muchos de la entidad

Tengo un model de datos central como tal: ParentObject <--->> ChildObject

Both ParentObject y ChildObject tienen un atributo levelNumber como:

 typedef enum { Primary, Secondary, Tertiary } LevelNumber; 

También tengo un método para convertir el número de nivel de int a cadena en ParentObject y childObject:

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

Ahora tengo un FetchedResultsController en una tableview que enumera el ParentObject . Lo que trato de get en el nombre de la sección es:

  • Si ParentObject es Secondary o Tertiary , muestre el nombre de la sección como Secondary o Tertiary .
  • Si ParentObject es Primary pero cualquiera de los ChildObjects es Secondary o Tertiary , muestre el nombre de la sección como Secondary o Tertiary .
  • Si ParentObject y todos los ChildObjects son Primary , muestre el nombre de la sección como Primary

Es bastante sencillo si solo tuviera que search en el levelNumber de ParentObject , algo así como el siguiente:

 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]; 

Entiendo que la restricción en FRC es que el resultado del SortDescriptor debería devolver los resultados en el mismo order en que se desea mostrar. ¿Cómo puedo incorporar las comprobaciones de ChildObject aquí también. ¿Sería un nuevo tipo de SortDescriptor, o algo más?

Eche un vistazo al código de ejemplo de Apple, DateSectionTitles, que explica cómo tener dates como secciones y cuáles usar también para su caso. La visualización real de la cadena que administra en titleForSection pero mantiene un atributo en la database que es "primitivo" y se puede clasificar, llamado sectionIdentifier .

En su caso particular, el identificador de sección sería como levelNumber y se calculará simplemente devolviendo el levelNumber de levelNumber más levelNumber de todos los niños.

El patrón es el siguiente:

 -(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; } 

Y no olvide reiniciarlo si las entidades cambian.

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

Finalmente, asegúrese de que sea inválido cuando cambien los datos relevantes:

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

Para supervisar los cambios en levelNumber de cualquier niño, los padres deben escuchar NSManagedObjectContextDidSaveNotification y ver si alguno de sus hijos está guardado.