ios - Custom Core Data SectionNameKeyPath
core-data transient (2)
Soy nuevo en los datos básicos y estoy tratando de descubrir cómo crear una sectionNameKeyPath
personalizadaNameKeyPath en mi NSFetchedResultsController
. Tengo un objeto administrado con un atributo llamado acctPeriod
. Es un NSString
. Quiero crear secciones basadas en los primeros 4 caracteres de este campo. Los primeros 4 caracteres representan el año del período contable y no es necesario guardarlos.
He revisado este sitio y he visto publicaciones sobre atributos transitorios, pero parece que no puedo hacer que funcionen. Básicamente, quiero esto y luego asignar periodYear
para mi sectionNameKeyPath
.
@dynamic periodYear;
-(NSString *)periodYear
{
return [self.acctPeriod substringToIndex:4];
}
Cualquier ayuda sería apreciada.
** ACTUALIZACIÓN: Utilizando la respuesta de Martin R., pude hacer que funcionara como esperaba.
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Billing" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"acctPeriod" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
//Predicate
NSPredicate *pred = [NSPredicate predicateWithFormat:@"clients = %@", self.client];
NSLog(@"%@",pred);
//[fetchRequest setResultType:NSDictionaryResultType];
//[fetchRequest setReturnsDistinctResults:YES];
[fetchRequest setPredicate:pred];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"periodYear" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
Lo siguiente debería funcionar: Implemente el método periodYear
(que se usará como "ruta de clave de nombre de sección") en una extensión de clase de su subclase de objeto gestionado:
@interface Event (AdditionalMethods)
- (NSString *)periodYear;
@end
@implementation Event (AdditionalMethods)
- (NSString *)periodYear {
return [self.acctPeriod substringToIndex:4];
}
@end
Asegúrese de que acctPeriod
se use como el primer (o único) descriptor de ordenación para la solicitud de búsqueda:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"acctPeriod" ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
Use periodYear
como sectionNameKeyPath
para el controlador de resultados obtenido:
NSFetchedResultsController *_fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:@"periodYear"
cacheName:nil];
_fetchedResultsController.delegate = self;
self.fetchedResultsController = _fetchedResultsController;
Y finalmente agregue el método predeterminado titleForHeaderInSection
:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo name];
}
Alternativamente, puede definir periodYear
como atributo transitorio del objeto gestionado. Tampoco se almacenará en la base de datos en ese caso, pero se puede implementar de forma tal que el valor se calcule a pedido y se almacene en caché.
El proyecto de muestra DateSectionTitles de Apple Developer Library demuestra cómo funciona esto.
Recomiendo que no se use una propiedad transitoria como sectionNameKeyPath
ya que dará como resultado la falla de todos los objetos obtenidos por la solicitud de recuperación, de modo que la propiedad se pueda usar como la ruta de sección.
Es mejor definir una propiedad persistente del year
y usarla como su sectionNameKeyPath
.
establece FRC sectionNameKeyPath
al year
como sectionNameKeyPath
:
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:@"year"
cacheName:nil/*your chioce*/];
para mostrar el nombre de la sección como un título en la tabla, implementar:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
id<NSFetchedResultsSectionInfo> sec = [self.fetchedResultsController sections][section];
return [sec name];
}