1

데이터 모델 구성을 기반으로 NSPredicate 개체를 만드는 데 문제가 있습니다.NSFetchedResultsController를 사용하여 많은 NSPredicate로

저는 Bob이라는 엔티티의 2 개와 Fred라는 하나의 엔티티가 있습니다. Bob은 'hasFreds'(역방향 hasBobs)라는 Fred와 다 대다 관계를 가지고 있고 Fred는 BOOL 유형의 hasEten 속성을 가지고 있습니다.

모든 Bob이 hasEaten = YES를 사용하여 적어도 하나의 Fred를 가진 Bob의 목록을 가져 오려고합니다. hasEaten = YES 인 프레드가 없으면 프레드가없는 모든 Bob을 반환하고 싶습니다.

이것은 내가 지금까지 가지고있는 것입니다. "hasEnt = Fred가없는 프레드가 없으면 Fred없이 모든 Bob을 반환하려고합니다."조건을 만족하지 못합니다 :

predicate1 = [NSPredicate predicateWithFormat: 
      @"(SUBQUERY(hasFreds, $fred, $fred.hasEaten = %@)[email protected] > 0)" 
      ,@YES]; 

    fr = [NSFetchRequest fetchRequestWithEntityName:@"Bob"]; 

    fr.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO selector:@selector(compare:)]]; 

    fr.predicate = predicate1; 


    NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fr managedObjectContext:[[self appDelegate] managedObjectContext] sectionNameKeyPath:nil cacheName:nil]; 
    fetchedResultsController.delegate = self; 

답변

1

나는 개념의 관점에서 보면 귀하의 조건이 실제로 하나의 검색어가 아니라고 생각합니다. 두 쿼리를 만들려고합니다. 하나는 다른 쿼리의 결과를 기반으로합니다. 이것은 사실 SQL 쿼리가 아니라 개체 그래프 조건자를 생각한 것입니다.

따라서 가장 간단하고 직관적 인 솔루션은 두 개의 버전의 가져온 결과 컨트롤러가 있어야한다고 생각합니다.

조건부를 동적으로 변경하여 다른 버전을 만듭니다. (나는이 패턴을 검색과 같이 많이 사용하고 있습니다.) 어쨌든 하위 쿼리가 영구 저장소에 두 번 이상 도달하기 때문에 페치 된 결과 컨트롤러에 대한 조건자를 설정하기 전에 조건을 평가하기 위해 하나의 효율적인 페치를 만들 수 있습니다. 필요한 경우

당신의 조건을 설정 한 후, 제거 : countForFetchRequest은 매우 효율적이고 더 메모리를 차지하지

if ([context countForFetchRequest:request] == 0) { 
    request.predicate = nil; 
} 
// continue creating your FRC with the request 

하는 것으로. 당신은 FRC의 캐시 기능을 활용해야하는 경우

업데이트하려면,

self.fetchedResultsController = nil; 
[self.tableView reloadData]; // or collection view 

, 위의 패턴 다음과 같은 두 가지 별도의 FRCS있는 솔루션도 가능하다.

+0

나는 당신의 해결책을 사용하여 비슷한 해결책을 제시했습니다. controllerDidChangeContent에서 countForFetchRequest를 사용하여 술어를 전환해야하는지 여부를 확인한 다음 필요할 경우 변경합니다. NSFetchedResultsController에게 performFetch를 알려주고 다시 시작하는 방법으로 변경 사항을 추적합니다. 나는 그것이 많은 도움이 되었기 때문에 대답을 표시 할 것입니다. –

+0

글쎄, 그것은 본질적으로 같은 해결책입니다. 그래서이 대답을 받아 들여야합니다. 이것은 FRC의 전달 메커니즘에 약간의 차이가 있습니다. 실제로 솔루션의 핵심은 아닙니다. – Mundi

0

사용자 Mundi 덕분에 솔루션을 찾을 수있었습니다. 먼저 getCorrectPredicate라는 메서드를 구현했습니다.

-(NSPredicate *)getCorrectPredicate{ 

     NSPredicate *predicate1; 
     NSFetchRequest *fr; 

     predicate1 = [NSPredicate predicateWithFormat: 
         @"(SUBQUERY(hasFreds, $fred, $fred.hasEaten = %@)[email protected] > 0)",@YES]; 

     fr = [NSFetchRequest fetchRequestWithEntityName:@"Bob"]; 

     fr.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO selector:@selector(compare:)]]; 

     fr.predicate = predicate1; 

     if([[[self appDelegate] managedObjectContext] countForFetchRequest:fr error:nil] == 0){ 
      // we have a none situation 
      self.predicateState = [NSPredicate predicateWithFormat: 
            @"[email protected]=0"]; 
     }else{ 
      self.predicateState = predicate1; 
     } 
     return self.predicateState; 
    } 

둘째

는 NSFetchedResultsController 위임 방법 controllerDidChangeContent 여부 술어 변화를 확인 하였다.

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{ 

     [_expensesTable endUpdates]; 

     [[[self frc] fetchRequest] setPredicate:[self getCorrectPredicate]]; 
     [self performFetch]; 
    } 
관련 문제