2013-04-08 18 views
14

Sono nuovo nei dati di base e sto cercando di capire come creare un numero personalizzato sectionNameKeyPath nel mio NSFetchedResultsController. Ho un oggetto gestito con un attributo chiamato acctPeriod. È un NSString. Voglio creare sezioni basate sui primi 4 caratteri di questo campo. I primi 4 caratteri rappresentano l'anno del periodo contabile e non è necessario salvarlo.Dati principali personalizzati SectionNameKeyPath

Ho visitato questo sito e ho visto post sugli attributi transitori ma non riesco a farli funzionare. Fondamentalmente voglio questo e quindi assegnare periodYear per il mio sectionNameKeyPath.

@dynamic periodYear; 

-(NSString *)periodYear 
{ 
    return [self.acctPeriod substringToIndex:4]; 
} 

Qualsiasi aiuto sarebbe apprezzato.

** AGGIORNAMENTO: Utilizzando la risposta di Martin R., sono riuscito a farlo funzionare come previsto.

- (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; 
} 

risposta

26

Il seguente dovrebbe funzionare: Implementare il metodo periodYear (che verrà utilizzato come "sezione chiave percorso percorso") in un'estensione di classe della sottoclasse dell'oggetto gestito:

@interface Event (AdditionalMethods) 
- (NSString *)periodYear; 
@end 

@implementation Event (AdditionalMethods) 
- (NSString *)periodYear { 
    return [self.acctPeriod substringToIndex:4]; 
} 
@end 

Assicurarsi che acctPeriod viene utilizzato come prima (o unica) sorta descrittore per la richiesta di recupero:

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"acctPeriod" ascending:YES]; 
NSArray *sortDescriptors = @[sortDescriptor]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

Usa periodYear come sectionNameKeyPath per i risultati inverosimile regolatore:

NSFetchedResultsController *_fetchedResultsController = [[NSFetchedResultsController alloc] 
        initWithFetchRequest:fetchRequest 
        managedObjectContext:self.managedObjectContext 
        sectionNameKeyPath:@"periodYear" 
           cacheName:nil]; 
_fetchedResultsController.delegate = self; 
self.fetchedResultsController = _fetchedResultsController; 

E infine aggiungere il metodo predefinito titleForHeaderInSection:

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

In alternativa, è possibile definire attributo transitorio dell'oggetto gestito. Anche in questo caso non verrà memorizzato nel database, ma può essere implementato in modo che il valore sia calcolato su richiesta e memorizzato nella cache.

Il progetto di esempio DateSectionTitles dalla libreria per sviluppatori Apple dimostra come funziona.

+0

OK, ha funzionato benissimo. Ho provato questo prima ma il problema è che sto provando solo a caricare 1 delle mie entità, acctPeriod, e ordinarlo per periodYear.Quindi stavo usando [fetchRequest setPropertiesToFetch: [NSArray arrayWithObjects: [entityProperties objectForKey: @ "acctPeriod"], nil]]; che non sembra funzionare. Ho provato a inserire periodYear come entityProperty ma so che non lo è. Viene visualizzato questo errore: "Periodo di chiavi non valideAnno passato a setPropertiesToFetch:" Qualche idea? – theDVUSone

+0

@theDVUSone: se usi 'propertiesToFetch', probabilmente dovrai definire' periodYear' come attributo transitorio e aggiungerlo a 'propertiesToFetch'. Non l'ho provato, ma è quello che presumo. –

+0

Stavo commettendo l'errore di dichiarare una proprietà @ che implementava un getter. Questa soluzione più o meno ha sottolineato che dovrebbe essere solo una dichiarazione di metodo. – JLust

8

raccomanda di non usare una struttura transitoria come sectionNameKeyPath come risulterà in fault di tutti gli oggetti ottenuti dalla richiesta di recupero così la proprietà può essere utilizzata come percorso sezione.
È meglio definire una proprietà persistente di year e utilizzarla come sectionNameKeyPath.
si imposta FRC sectionNameKeyPath a year in questo modo:

[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
            managedObjectContext:self.managedObjectContext 
             sectionNameKeyPath:@"year" 
               cacheName:nil/*your chioce*/]; 

per visualizzare il nome della sezione come titolo nella tabella, implementare:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{ 
    id<NSFetchedResultsSectionInfo> sec = [self.fetchedResultsController sections][section]; 
    return [sec name]; 
}