깊은 관계를 위해 핵심 데이터와 함께 NSPredicate 사용
-
19-09-2019 - |
문제
NSARRAYCONTROLLER가 있습니다. companiesController
최상위 핵심 데이터 엔티티에 묶여 Companies
.
ㅏ Company
많이있다 Department
S, a Department
많이있다 Employee
; 이들은 1 대가 된 관계로 표현되며 departments
그리고 employees
.
속성을 기반으로합니다 salary
의 Employee
UI 통한 방법 내부의 급여를 기준으로 필터링을 위해 동적으로 할 수 있다고 생각했습니다.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY departments.employees.salary < %@", [NSNumber numberWithInt:23000]];
[companiesController setFilterPredicate:predicate];
아아, 이것은 나에게 오류를 준다 : -[NSCFSet compare:]: unrecognized selector sent to instance
.
해결책
이 경우 여러 대의 키가 허용되지 않습니다.
대신 다음을 수행 할 수 있습니다.
- 부서 엔티티에 "필터"플래그 (부울) 속성을 추가하여 데이터 모델을 수정하십시오.
- 메소드를 만듭니다 : 모든 부서 개체를 가져와, 술어의 후반기 기준을 충족하는 부서의 경우 필터 플래그를 YES로 설정하고 다른 부서의 경우 필터 플래그를 NO로 설정하고 저장하십시오.
- 회사 술어에서 필터 플래그를 사용하십시오.
코드 변경 (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];
그리고 새로운 방법 (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();
}
}
다른 팁
하위 쿼리를 사용 하여이 작업을 수행 할 수도 있습니다.
모든 부서를 구입하십시오. '관계는'관계는 회사의 부서의 역수입니다.
-(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];
}
또는 더 많은 회사가 있고 급여를받는 직원이있는 회사를 원하는 경우, 일부 금액보다 더 높습니다. 하위 퀘스트의 결과를 기반으로 한 하위 퀘스트
-(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];
}
제휴하지 않습니다 StackOverflow