objective-c ios core-data nsfetchedresultscontroller

objective c - Obtener NSFetchedResultsController, NSSortDescription y sectionNameForKeyPath para trabajar juntos



objective-c ios (4)

Probablemente necesite subclasificar NSFetchedResultsController y personalizar las funciones de nombre de sección. Consulte los documentos de la clase NSFetchedResultsController en la creación de subclases.

Actualmente estoy trabajando en una aplicación que tiene un par de entidades y relaciones como se ilustra a continuación:

Artículo << -> Categoría .

Actualmente estoy obteniendo instancias de elementos y mostrándolas en secciones usando category.name del elemento. En este caso, puedo usar un descriptor de clasificación para ordenar las categorías por nombre, lo cual es bastante sencillo y funciona bien (código relevante a continuación):

-(NSFetchedResultsController*)fetchedResultsController { if (fetchedResultsController_ != nil) return fetchedResultsController_; NSManagedObjectContext *moc = [order_ managedObjectContext]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:moc]; [fetchRequest setEntity:entity]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"category.name" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; [sortDescriptors release]; [sortDescriptor release]; NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc sectionNameKeyPath:@"category.name" cacheName:nil]; controller.delegate = self; self.fetchedResultsController = controller; [controller release]; [fetchRequest release]; NSError *error = nil; if (![fetchedResultsController_ performFetch:&error]) { // Error handling } return fetchedResultsController_; }

Mi problema ahora es que necesito ordenar estas categorías no por nombre, sino por un (NSNumber*) displayOrder que es parte de la entidad Category . PERO necesito los títulos de la sección en la vista de tabla para continuar usando el name la categoría.

Si configuro sortDescriptor para usar category.displayOrder y mantengo sectionNameKeyPath como category.name , los títulos de las secciones funcionan bien pero el sortDescriptor simplemente es ignorado por el fetchedResultsController y las secciones de la tabla están ordenadas por el nombre de la categoría (¿no está seguro de por qué?) .

Mi siguiente idea fue sobrescribir el método displayOrder getter pero eso no me llevó demasiado lejos ya que los tipos de devolución son diferentes, además necesitaba el valor de displayOrder para la clasificación de sección.

Así que ahora tengo una solución que se siente un poco torpe (código a continuación), y me pregunto si hay una mejor manera de lograr lo mismo usando el control de resultados fetched solo.

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section // The code below grabs a reference to first object for a given section // and uses it to return the associated category name { id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; NSArray *menuItems = [sectionInfo objects]; if ([menuItems count] > 0) { MenuItem *menuItem = [menuItems objectAtIndex:0]; NSString *categoryName = menuItem.category.name; return categoryName; } return [sectionInfo name]; }

¿Me estoy perdiendo algo básico aquí?

Gracias de antemano por sus pensamientos.

Rog


En cuanto a la clasificación, la documentación dice lo siguiente:

Si el controlador genera secciones, el primer descriptor de clasificación de la matriz se usa para agrupar los objetos en secciones; su clave debe ser la misma que sectionNameKeyPath o el orden relativo usando su clave debe coincidir con sectionNameKeyPath.

En inglés (es posible que ya conozcas a este Rog, pero es posible que no y ciertamente las personas que busquen más tarde puedan apreciar la explicación), eso significa que si estás usando secciones, entonces la clasificación en NSFetchRequest debe agrupar todos los elementos en el mismo sección juntos. Esto podría ser haciendo que los primeros criterios de clasificación sean el campo utilizado como el nombre de la sección, o podría ser haciendo que los primeros criterios de clasificación sean algo más que resulte en el mismo tipo de agrupamiento.

La documentación no especifica qué pasa si lo arruinas; es posible que arruine por completo los nombres de las secciones, repita secciones, omita secciones, detecte la situación y "corrija" su clasificación, o incluso simplemente cuelgue. ¿Alguna de sus categorías tiene el mismo displayOrder?

Su solución es ciertamente viable, y si no puede hacer que funcione correctamente ordenando por displayOrder mientras titula secciones por categoría.nombre, probablemente sea su mejor solución.


¿Por qué estás buscando Item y no Category ? Si entiendo sus relaciones correctamente, Category posee una relación de 1 a muchos con Item , por lo que, en teoría, una instancia de Category debe tener una propiedad de ''elementos'' que devuelva cada Item en esa categoría.

Si ese es el caso, entonces simplemente puede buscar todas sus categorías y luego ordenarlas por displayOrder . Luego, olvídate de usar secciones en el NSFetchedResultsController . En cambio, sus métodos tableView asociados se tableView como:

- (NSInteger)numberOfSections { return [[self.fetchedResultsController fetchedObjects] count]; } - (NSInteger)numberOfRowsInSection:(NSInteger)section { Category* category = [[self.fetchedResultsController fetchedObjects] objectAtIndex:section]; return [[category items] count]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { Category* category = [[self.fetchedResultsController fetchedObjects] objectAtIndex:section]; return category.name; }

En resumen, creo que está complicando las cosas al obtener Item lugar de Category , y al tratar de hacer que NSFetchedResultsController administre su agrupación de sección por usted. Es mucho más simple y requiere mucho menos código para hacer solo la gestión de sección usted mismo.


Esa es una solución perfectamente buena para el problema, Rog.

Ciertamente no quiere / necesita subclase NSFetchedResultsController.

@aroth, no tenemos suficiente información para conocer los detalles de su modelo de objeto, pero los nombres ciertamente implican que esa categoría no posee el artículo. El artículo tiene una categoría. Su intención es mostrar una lista de elementos, es por eso que está buscando elementos.