2010-12-08 18 views
9

Actualmente tengo una opción que permite a un usuario cambiar el orden de visualización de una categoría en mi aplicación de iPhone.NSFetchedResultsSolicitud de sección del controlador usando la orden de visualización

Quiero seccionar la vista de tabla utilizando un NSFetchedResultsController para que los títulos de sección sean los "category.name" ordenados por "category.displayOrder" donde "categoría" tiene una relación TO-ONE con la entidad que estoy buscando. La única forma en que puedo hacer que la sección funcione correctamente es usando "category.displayOrder" como el título de la sección.

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"category.displayOrder" ascending:YES]; 
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 

NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil]; 

[fetchRequest setSortDescriptors:sortDescriptors]; 

[fetchRequest setFetchBatchSize:10]; 

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                            managedObjectContext:managedObjectContext 
                             sectionNameKeyPath:@"category.name" 
                               cacheName:nil]; 

¿Alguna idea sobre cómo puedo nombrar el título de la sección algo diferente de la propiedad que estoy ordenando?

Respuesta

14

No estoy seguro si entiendo su pregunta por completo, pero sí algo parecido en mi aplicación y aquí es cómo conseguir que funcione:

En primer lugar, el método fetchedResultsController, donde hice las descripciones ordenar y predicados basa en lo que intento hacer En este caso, quiero ordenar los títulos de las películas por fecha de lanzamiento ENTONCES por su nombre. Luego, con mi predicado, tomo entidades de un "tipo" específico y dentro de un cierto rango de 'ReleaseDate'.

En mi definición fetchresultscontroller, estableces sectionNameKeyPath en "releaseDate" para que mis encabezados de sección se basen en una fecha.

- (NSFetchedResultsController *)fetchedResultsController { 

    if (fetchedResultsController_ != nil) { 
     return fetchedResultsController_; 
    } 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSSortDescriptor *sortByReleaseDate = [[NSSortDescriptor alloc] initWithKey:@"releaseDate" ascending:NO]; 
    NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByReleaseDate,sortByName, nil]; 
    [fetchRequest setSortDescriptors:sortDescriptors]; 
    [sortDescriptors release]; 
    [sortByName release]; 
    [sortByReleaseDate release];    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(type == 'Movies') AND (releaseDate <= %@) AND (releaseDate >= %@)", [NSDate date], [NSDate dateWithTimeIntervalSinceNow:kOneDayTimeInterval*-30]]; 
    [fetchRequest setPredicate:predicate]; 

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Movie" inManagedObjectContext:self.managedObjectContext]; 
     [fetchRequest setEntity:entity]; 

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"releaseDate" cacheName:nil]; 

    ...// Perform and return fetch here, error handling etc... 

    return fetchedResultsController_; 

}  

Luego, en mi punto de vista mesa de métodos de delegado fuente de datos, vuelvo el título real de cada cabecera después de transformar mi NSDate en NSString (recuerda que tienes que volver NSString para un título de cabecera tableview.

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 

    NSString *rawDateStr = [[[self.fetchedResultsController sections] objectAtIndex:section] name]; 
    //convert default date string to NSDate... 
    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; 
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZ"]; 
    NSDate *date = [formatter dateFromString:rawDateStr]; 

    //convert NSDate to format we want... 
    [formatter setDateFormat:@"d MMMM yyyy"]; 
    NSString *formattedDateStr = [formatter stringFromDate:date]; 
    return formattedDateStr; 

} 

Así que si quería cambiar la forma en que se está mostrando mis datos a ser organizado por titleName por ejemplo, que cambiaría mi objetivo fetchedResultsController a:

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"titleName" cacheName:nil]; 

Y modificar mi tableview: titleForHeaderInSection: Método de fuente de datos simplemente devolver el titleName (que ya es una cadena):

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 

     return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; 
} 

Espero que esto ayude a encontrar una solución a su problema específico.

Saludos, Rog

+1

Estoy tratando de ordenar mis secciones por displayorder (NSInteger), pero en vez de mostrar el número entero como el título de la sección, me gustaría mostrar el nombre que corresponde a la displayorder. Entonces, en lugar de tener títulos de sección 1, 2 y 3, tendría "Nombre", "Segundo nombre" y "Tercer nombre". ¿Crees que la mejor manera es determinar el título según el orden de visualización en titleForHeaderInSection? – avenged

+0

Es la única forma que yo sepa. Puede hacer un cambio en displayOrder y luego devolver la sección correspondiente que desea mostrar. – Rog

+0

Esperaba que no tuviera que realizar otra búsqueda dentro de titleForHeaderInSection, pero no parece que haya otra manera ... – avenged

3

Gracias a Rog yo era capaz de envolver mi cabeza en torno a este problema y llegar a una solución. No es tan limpio como me gustaría, así que si alguien tiene un mejor enfoque, me encantaría saberlo.

Según lo que he aprendido (podría estar equivocado, por favor, avíseme), solo puede nombrar secciones (sectionNameKeyPath) por la propiedad en la que está ordenando su tabla. En mi caso, quería ordenar mi tabla usando una propiedad llamada displayOrder, pero no quería que los títulos de mis secciones fueran 0, 1, 2, etc. En cambio, quería que los títulos de las secciones usaran la propiedad del título "Name1", "Name2", etc. que corresponde a displayOrder. Para ello determino el título de cabecera en base a la displayorder en titleForHeaderInSection:

 NSString *displayOrder = [sectionInfo name]; 

     NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
     [fetchRequest setEntity:[NSEntityDescription entityForName:@"Platform" inManagedObjectContext:managedObjectContext]]; 

     NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init]; 
     [numberFormatter setNumberStyle:NSNumberFormatterNoStyle]; 

     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"displayOrder == %@", [numberFormatter numberFromString:displayOrder]]; 
     [fetchRequest setPredicate:predicate]; 

     Platform *platform; 
     NSError *error = nil; 
     NSArray *fetchResults = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
     if ([fetchResults count] > 0) { 
      platform = [fetchResults objectAtIndex:0]; 
      headerView.titleLabel.text = [platform name]; 
     } else { 
      headerView.titleLabel.text = @"Unknown"; 
     } 

     [numberFormatter release]; 
     [fetchRequest release]; 

Gracias Rog!

+0

No me preocupo Me alegro de que haya sido útil. – Rog

+0

@avenged, ¿cómo demonios lo descubriste? "De acuerdo con lo que he aprendido (podría estar equivocado, por favor, avíseme), solo puede nombrar secciones (sectionNameKeyPath) por la propiedad en la que está ordenando su tabla". ¡Eso me estaba matando! ¡Gracias! –

9

Tuve el mismo problema y tengo otra solución: use una propiedad transitoria para la sección Nombre clave clave, es decir, category.sectionName.Parece que si utiliza una propiedad de datos centrales como sectionNameKeyPath, intentará ordenar con eso.

Así, utilizando el ejemplo anterior:

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"category.displayOrder" ascending:YES]; 
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"category.sectionName" cacheName:nil]; 

Category.h:

@interface Category : NSManagedObject 

@property (nonatomic, retain) NSString* name; 
@property (nonatomic, retain) NSNumber* displayOrder; 

-(NSString*) sectionName; 

@end 

Category.m:

@implementation Category 

@dynamic name; 
@dynamic displayOrder; 

-(NSString*) sectionName{ 
    return self.name; 
} 

@end 

Luego, en el controlador de vista:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 
    id<NSFetchedResultsSectionInfo> sectionInfo=[self.resultsController.sections objectAtIndex:section]; 
    return sectionInfo.name; 
} 
+0

Esto funcionó para mí, ¡gracias! –

0

En mi caso tuve que RTFM:

- initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName:

Si esto sectionNameKeyPath no es el mismo que el especificado por el primer descriptor tipo en fetchRequest, que deben generar el mismos pedidos relativos. Por ejemplo, el primer descriptor de clasificación en fetchRequest podría especificar la clave para una propiedad persistente; sectionNameKeyKey podría especificar una clave para una propiedad transitoria derivada de la propiedad persistente.

Qué estaba creando inconsistencias en la Tabla de pedido cuando ya sea la propiedad o sectionNameKeyPathNSSortDescriptor del objeto administrado cambió a un orden diferente al de la otra propiedad.

Fuente:
https://richardwarrender.com/2010/10/core-data-objects-in-wrong-sections/

Cuestiones relacionadas