2009-09-05 22 views
13

Estoy haciendo una tabla seccionada con resultados obtenidos, pero estoy teniendo problemas para obtener secciones personalizadas.Usar secciones personalizadas con NSFetchedResultsController?

Normalmente, uno solo tiene un atributo para ordenar, y usa sectionNameKeyPath: para generar las secciones. Pero mi atributo de clasificación se calcula sobre la marcha, y me parece que no puede conseguir el fetchedResultsController usarlo correctamente ...

Actualización: Usando jbrennan 's consejos a continuación, estoy muy cerca de la prevista funcionalidad. Agregué una Categoría al NSDate que devuelve un número de "días atrás"; poner eso aquí me da secciones sobre la base de esos números:

NSFetchedResultsController *aFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
    managedObjectContext:managedObjectContext 
    sectionNameKeyPath:@"myDateAttribute.daysAgo" 
    cacheName:@"Root"]; 

Aquí es donde estoy atascado: no necesito de ellos ordenados por "hace días," Los necesito ordenados a través de algunos cálculos basados ​​en otra atributos en la entidad. Así que no puedo acaba de llamar a ese método personalizado Categoría, tengo que llamar a un método con argumentos , así:

[myDateAttribute sortingRoutine:thisObject.value] 

O algo por el estilo. Espero que tenga algún sentido. Gracias muchísimo si puedes ayudar :)

Respuesta

6

Puede intentar lo siguiente.

Agregue un atributo transitorio a su modelo de datos central en la entidad Tarea. A continuación, implemente el método

- (void)awakeFromFetch 

en su clase Task NSManagedObject. Vea su documentación. Dentro del método, se le permite establecer un valor para la propiedad transitoria usando los valores de las otras propiedades. Tenga en cuenta que hay algunas restricciones sobre lo que puede hacer, pero esto está bien explicado en la documentación (lo más notable es que no puede modificar relaciones o pasar argumentos; sin embargo, si puede calcular su propiedad transitoria utilizando solo los valores de las otras propiedades/relaciones, debería estar perfectamente bien).

Una vez que haya hecho esto, simplemente use la propiedad transitoria como el atributo que pasa para recuperar las secciones.

+0

Aha! Esto funcionó maravillosamente, gracias. Ahora la aplicación se bloquea al guardar nuevas Tareas, pero voy a trabajar en eso un poco y publicar una pregunta por separado si es necesario. :) – Triz

+0

Su aplicación no debe bloquearse al guardar: las propiedades transitorias no se almacenan, por lo tanto, esto no puede ser la causa de ninguna manera. –

+0

En realidad, no se bloquea durante el proceso de guardado, sino * después *, cuando la vista vuelve a la tabla seccionada. No estaba haciendo esto antes de estos cambios, y no he hecho nada más, así que creo que está relacionado. Tal vez 'awakeFromFetch:' no se está llamando cuando reaparece la vista? – Triz

16

Hice algo similar a esto en una (próximamente) aplicación de envío de iPhone. Mis secciones fueron divididas por fechas como esta: Ayer, Hoy, Mañana, En el futuro ...

De todos modos, el truco para mí fue agregar una Categoría a NSDate para determinar en qué sección pertenecía el objeto buscado.

Mi objeto administrado tenía una propiedad llamada dueDate, que era un NSDate. Al configurar el controlador de resultados obtenidos, utilicé @"dueDate.relativeDate" como la ruta de la clave de sección.

en la categoría, -relativeDate fue declarado como devolver un NSString y también como una propiedad readonly (cualquiera de los cuales podría ser suficiente, no lo intente sin tener ambas cosas, pero no hace daño tener un método y propiedad declaración). Luego simplemente implementé el método funcionó maravillosamente.

+0

acuerdo, creo que estoy contigo allí.Sin embargo, ¿qué ocurre si mis NSDates están realmente en una entidad separada? Tengo 'Tareas' como las entidades principales que se obtienen, y 'Restablecimientos' están relacionadas (-to-many). Así que cada 'Tarea' tiene un montón de fechas' Restablecer', siendo la más reciente la más importante aquí. Lo que probé fue usar '@" reset.specialDateMethod' como la clave de clasificación, pero no me gusta eso ... – Triz

+0

Depende de lo que haga su 'specialDateMethod'. En ese método, probablemente podría filtrar a través de su conjunto de Reinicia con NSPredicate para encontrar el más importante, y luego usa su 'fecha' como prefieras. También puedes guardar el' Restablecer' porque imagino que sería caro. Quizás tu 'Tarea' podría tener una propiedad como" mostRecentReset" o lo que es relevante – jbrennan

+0

Más al punto:. ¿Cuál es' sectionNameKeyPath:??. 'esperando ¿tiene que ser una cadena, lo que corresponde a un atributo de la entidad creo que aquí es donde estoy confundido – Triz

0

Aquí hay un montón de código para lograr esto (gracias jbrennan):

@implementation NSDate (MyExtensions) 


// Return today. 
+ (NSDate *)today { 

    return [NSDate date]; 
} 


// Return yesterday (today minus 24 hours). 
+ (NSDate *)yesterday { 

    return [NSDate dateWithTimeIntervalSinceNow:-60*60*24]; 
} 


// Return tomorrow (today plus 24 hours). 
+ (NSDate *)tomorrow { 

    return [NSDate dateWithTimeIntervalSinceNow:60*60*24]; 
} 


// Convert a date comporting a time into a rounded date (just the day, no time). 
- (NSDate *)dayDate { 

    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 
    NSDateComponents *comps = [[NSCalendar currentCalendar] components:unitFlags fromDate:self]; 
    return [[NSCalendar currentCalendar] dateFromComponents:comps]; 
} 


// Return a string representing the date relatively (today, tomorrow, yesterday, etc.) 
// If no relative sentence is found, return the NSDateFormatterLongStyle formatted date. 
- (NSString *)relativeDate { 

    if ([self.dayDate isEqualToDate:[[NSDate today] dayDate]]) { 

     return NSLocalizedString(@"Today", @"NSDate extensions"); 
    } 
    if ([self.dayDate isEqualToDate:[[NSDate yesterday] dayDate]]) { 

     return NSLocalizedString(@"Yesterday", @"NSDate extensions"); 
    } 
    if ([self.dayDate isEqualToDate:[[NSDate tomorrow] dayDate]]) { 

     return NSLocalizedString(@"Tomorrow", @"NSDate extensions"); 
    } 

    return [NSDateFormatter localizedStringFromDate:self 
              dateStyle:NSDateFormatterLongStyle 
              timeStyle:NSDateFormatterNoStyle];  
} 


@end 
+1

Esto es antiguo, pero cualquiera que lea esto: NO use constantes de segundos como esa, use las funciones NSCalendar. Ve a ver cualquier charla de la WWDC en las fechas –

Cuestiones relacionadas