Mit NSPredicate mit Core Data für tiefe Beziehungen
-
19-09-2019 - |
Frage
Ich habe eine NSArrayController, companiesController
auf eine Top-Level-Unternehmen Core Data gebunden, Companies
.
Ein Company
hat viele Department
ist, und ein Department
viele Employee
hat; diese wird durch die 1-zu-viele Beziehungen, departments
und employees
vertreten.
Basierend auf dem Attribut salary
ein Employee
ich dachte ich, das dynamisch in einer UI genannten Methode auf Gehalt basierte Filterung tun könnte:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY departments.employees.salary < %@", [NSNumber numberWithInt:23000]];
[companiesController setFilterPredicate:predicate];
Ach, das gibt mir die Fehlermeldung:. -[NSCFSet compare:]: unrecognized selector sent to instance
Lösung
Mehrere to-many-Tasten sind in diesem Fall nicht erlaubt.
Stattdessen könnten Sie die folgenden Schritte ausführen:
- Ändern des Datenmodell eines „Filter“ Flag (Boolean) Attributs an die Abteilung Einheit durch Zugabe.
- Erstellen Sie eine Methode an: holen alle die Abteilung Objekte, die Filter-Flag auf JA für die Bereiche festgelegt, die die Kriterien der zweiten Hälfte Ihres Prädikat erfüllen, stellen Sie die Filter-Flag auf NO für die anderen Abteilungen und speichern.
- Verwenden Sie das Filterhinweiszeichen in der Gesellschaft Prädikat.
Code-Änderungen (Schritt 3):
//NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY departments.employees.salary < %@", [NSNumber numberWithInt:23000]];
[self setDeptFilter:23000];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY depts.filter == YES"];
[companiesController setFilterPredicate:predicate];
Und das neue Verfahren (Schritt 2):
- (void)setDeptFilter:(NSUInteger)salary {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Department" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error = nil;
// fetch all Department objects
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
if (error) {
NSLog(@"Error fetching Departments %@, %@", error, [error userInfo]);
abort();
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY emps.salary < %@",[NSNumber numberWithInteger:salary]];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
// set filter flag to YES for the departments that meet the criteria
for (Department *dep in filterArray) {
dep.filter = [NSNumber numberWithBool:YES];
}
NSMutableArray *diffArray = [array mutableCopy];
[diffArray removeObjectsInArray:filterArray];
// set filter flag to NO for the departments that do NOT meet the criteria
for (Department *dep in diffArray) {
dep.filter = [NSNumber numberWithBool:NO];
}
[diffArray release];
// save
if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
Andere Tipps
Sie können auch tun dies Subqueries verwendet wird.
Holen Sie sich alle Abteilungen. Die ‚von‘ Beziehung ist die Umkehrung der Gesellschaft zu vielen Abteilungen:
-(void)printDepartmentsWithSalaryHigherThan:(int)salary inContext:(NSManagedObjectContext *)context {
NSFetchRequest *request = [[NSFetchRequest alloc ]init];
request.entity = [NSEntityDescription entityForName:@"Department" inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(employees, $emp, $emp.salary > %@ ).@count > 0", [NSNumber numberWithInt:salary]];
for(Department *dep in [context executeFetchRequest:request error:nil]){
NSLog(@"Department: %@", dep.depName);
NSLog(@"in Company: %@", dep.of.compName);
}
[request release];
}
Oder, wenn Sie mehr Unternehmen haben und wollen nur die Unternehmen, die einen Mitarbeiter mit einem Gehalt ‚höher als‘ einen gewissen Betrag haben. Eine Unterabfrage basierend auf dem Ergebnis einer Unterabfrage
-(void)printCompaniesWithHigherSalaryThan:(int)salary inContext:(NSManagedObjectContext *)context {
NSFetchRequest *request = [[NSFetchRequest alloc ]init];
request.entity = [NSEntityDescription entityForName:@"Company" inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(departments, $dep, SUBQUERY($dep.employees,$emp,$emp.salary > %@).@count > 0 ).@count > 0", [NSNumber numberWithInt:salary]];
for(Company *c in [context executeFetchRequest:request error:nil]){
NSLog(@"Company: %@", c.compName);
}
[request release];
}