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.