2013-04-08 7 views
14

Ich bin neu bei Kerndaten und versuche herauszufinden, wie Sie eine benutzerdefinierte sectionNameKeyPath in meinem NSFetchedResultsController erstellen. Ich habe ein verwaltetes Objekt mit einem Attribut namens acctPeriod. Es ist ein NSString. Ich möchte Abschnitte basierend auf den ersten 4 Zeichen dieses Feldes erstellen. Die ersten 4 Zeichen stellen das Jahr des Abrechnungszeitraums dar und müssen nicht gespeichert werden.Benutzerdefinierte Kerndaten SectionNameKeyPath

Ich bin durch diese Seite gegangen und habe Beiträge über transiente Attribute gesehen, aber ich kann nicht scheinen, sie zur Arbeit zu bringen. Grundsätzlich möchte ich dies und dann periodYear für meine sectionNameKeyPath zuweisen.

@dynamic periodYear; 

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

Jede Hilfe wäre willkommen.

** UPDATE: Mit Martin R. Antwort konnte ich es wie erwartet funktionieren.

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

Antwort

26

Folgende Arbeiten sollten: Umsetzung der periodYear Methode (die als "Abschnitt Name Schlüsselpfad") in einer Klassenerweiterung Ihrer verwalteten Objektunterklasse verwendet wird:

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

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

Stellen Sie sicher, dass acctPeriod als erste verwendet wird (oder nur) sortieren Descriptor für die Abrufanforderung:

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

Verwenden periodYear als sectionNameKeyPath für die abgerufenen Ergebnisse Controller:

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

Und schließlich Fügen Sie den Standard titleForHeaderInSection Methode hinzu:

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

Alternativ können Sie periodYear als Transientenattribut des verwalteten Objekts definieren. Es wird in diesem Fall auch nicht in der Datenbank gespeichert, kann aber so implementiert werden, dass der Wert bei Bedarf berechnet und zwischengespeichert wird.

Das Beispielprojekt DateSectionTitles aus der Apple Developer Library demonstriert, wie das funktioniert.

+0

OK, das hat super funktioniert. Ich habe das schon einmal versucht, aber das Problem ist, dass ich versuche nur 1 meiner Entitäten, acctPeriod, zu laden und sie nach periodYear zu sortieren.Also habe ich verwendet [fetchRequest setPropertiesToFetch: [NSArray arrayWithObjects: [entityProperties objectForKey: @ "acctPeriod"], nil]]; das scheint nicht zu funktionieren. Ich habe versucht, periodYear als entityProperty zu setzen, aber ich weiß, dass es nicht ist. Ich erhalte diesen Fehler: 'Ungültiger Schlüsselpfad periodYear wurde an setPropertiesToFetch übergeben:' Irgendwelche Gedanken? – theDVUSone

+0

@theDVUSone: Wenn Sie 'propertiesToFetch' verwenden, müssen Sie wahrscheinlich' periodYear' als transientes Attribut definieren und es zu 'propertiesToFetch' hinzufügen. Ich habe es nicht versucht, aber das nehme ich an. –

+0

Ich machte den Fehler, eine @property zu deklarieren, die einen Getter implementierte. Diese Lösung hat mehr oder weniger darauf hingewiesen, dass es sich nur um eine Methodendeklaration handeln sollte. – JLust

8

Ich empfehle eine vorübergehende Eigenschaft als sectionNameKeyPath gegen die Verwendung, da es nur in Verwerfungen alle Objekte, die durch die Abrufanforderung führen, so dass die Eigenschaft als Abschnitt Pfad verwendet werden könnte.
Sie definieren eine persistente Eigenschaft besser und verwenden sie als Ihre sectionNameKeyPath.
setzen Sie FRC sectionNameKeyPath zu year wie so:

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

in der Tabelle den Abschnittsnamen als Titel angezeigt werden, implementieren:

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