2012-04-25 16 views
30

Powrót znowu potrzebować więcej pomocy przy konstruowaniu moje NSPredicates :(Łącząc „I” i „OR” Stan w NSPredicate

Category 
{ 
    name:string 
    subs<-->>SubCategory 
} 

SubCategory 
{ 
    name:string 
    numbervalue:NSNumber 
} 

chciałbym wiedzieć, jak utworzyć orzecznik z I i LUB .

na przykład, chciałbym wrócić każdej kategorii o nazwie == „CATEGORY_NAME”, który ma także podkategorię z numbervalue z „ZMIENNAa” LUB „valueB”.

Próbowałem każdej możliwej kombinacji konstruktorów predykatów, z którymi mogłem wymyślić, ale po prostu nie mogę jej uruchomić.

To moja najlepsza jak dotąd próba.

NSPredicate *predicate=[NSPredicate [email protected]"(name== %@) AND (ANY subs.numbervalue==%@ OR ANY subs.numbervalue==%@)", @"aname", value1, value2]; 

Edycja 1

druga próba. Filtrowanie wartości "numbervalue" nadal nie działa.

NSNumber valueA=[NSNumber numberWithInt:20]; 
NSNumber valueA=[NSNumber numberWithInt:90]; 
NSArray *arr=[NSArray arrayWithObject:valueA,valueB,nil]; 

predicate=[NSPredicate predicateWithFormat:@"(name==%@)AND(ANY subs.numbervalue IN %@)",@"aname",arr]; 

Edycja 2

Próbowałem filtrowanie tylko przez numberValue i opuściły imienia alltogether.

1) użycie tego skutkuje zwróceniem całego zestawu, nawet jeśli tylko 1 pozycja w zestawie ma tę wartość.

predicate=[NSPredicate predicateWithFormat:@"(ANY subs.numbervalue IN %@)",arr]; 

2) Korzystanie Skutkuje to tym samym problemem, każda pozycja w zestawie są zwracane nawet jeżeli tylko 1 z nich pasuje.

predicate=[NSPredicate predicateWithFormat:@"((SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@)[email protected] > 0)", value1, value2]; 

Również użycie najprostszej wersji powoduje ten sam problem .... Nie zauważyłem tego wcześniej.

NSPredicate *predicate=[NSPredicate [email protected]"(ANY subs.numbervalue==%@ ,valueA]; 

Więc myślę, że mój problem został zawężony.

Kategoria jest podmiotem. Podkategoria to Podmiot.

Kategoria ma związek jeden do wielu z podkategorią i jest reprezentowana jako NSSet podkategorii.

Każda podkategoria ma atrybut o nazwie numbervalue.

Edycja 3

Aby przetestować Mam 2 Kategorie. Obie kategorie mają 10 subsów, z których każda ma wartość liczbową od 1 do 10;

Za pomocą tego kodu obie kategorie są zwracane wraz ze wszystkimi 10 subs dla każdego.

Oczekiwany wynik to obie kategorie zwrócone, każda z zaledwie 2 subsami.

Wykreślam wszystkie moje obiekty i dane są poprawne. Problem polega na tym, że nie mogę zwrócić kategorii, która filtrowała subs.

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSManagedObjectContext *context=[[DataSource sharedDataSource]managedObjectContext]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

[fetchRequest setFetchBatchSize:20]; 

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil]; 

NSPredicate *predicate; 
NSNumber *a=[NSNumber numberWithFloat:1]; 
NSNumber *b=[NSNumber numberWithFloat:2]; 
predicate=[NSPredicate predicateWithFormat:@"(SUBQUERY(subs,$x,$x.numbervalue==%@ or $x.numbervalue==%@)[email protected]> 0)",a,b]; 

[fetchRequest setPredicate:predicate]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

NSError *error = nil; 
[NSFetchedResultsContoller deleteCacheWithName:nil]; 

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"name" cacheName:@"Master"]; 
aFetchedResultsController.delegate = self; 

self.fetchedResultsController = aFetchedResultsController; 

if (![self.fetchedResultsController performFetch:&error]) { 

    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 
+0

Czy można sprawdzić 'NSCompoundPredicate'? To powinno ci pomóc. Spróbuj także użyć '... ORAZ (DOWOLNA liczba.wymagów IN% @)", @ "fooName", numArray' – Eimantas

+0

dzięki za porady – dubbeat

+0

użyj $ x.numbervalue, a nie $ numbervalue.Następnie spróbuj ustawić cache do zera najpierw i zobacz wynik ... –

Odpowiedz

32

Wykonam następujące czynności przy użyciu SUBQUERY.

[NSPredicate [email protected]"(name == %@) AND (SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@)[email protected] > 0)", @"aname", value1, value2]; 

Spróbuj i daj mi znać.

Innym rozwiązaniem mogłoby być złapać całą kolekcję subs a następnie filtrować Źródło zestaw z orzecznika aby sprawdzić, czy elementy pasujące do value1 lub value2.

Mam nadzieję, że to pomaga.

Edit

Jeśli zastosujemy Eimantas sugestia zrobić, aby upewnić się, aby stworzyć odpowiednią tablicę:

NSNumber valueA = [NSNumber numberWithInt:20]; 
NSNumber valueB = [NSNumber numberWithInt:90]; 
NSArray *arr = [NSArray arrayWithObjects:valueA, valueB, nil]; 
+0

, co zdaje się dziać, jeśli zbiór subskrypcji ma wartość liczbową 90 na przykład, ale reszta to 0, cała kolekcja subskrypcji nadal otrzymuje returnd – dubbeat

+0

Spróbuj użyć tylko * (SUBQUERY (subs, $ x, $ x.numbervalue ==% @ lub $ x.numbervalue ==% @). @ count> 0) * w predykacie i filtruje tablicę z dodatkowym predykatem, aby znaleźć to Nazwa. –

+0

Jakiego wyniku używasz tylko z SUBQUERY? –

49

Dodatek do odpowiedzi @ Stuarta, można użyć NSCompoundPredicate dla OR & i operacji takich jak ta.

obj-C - albo

// OR Condition // 

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; 
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; 
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]]; 

obj-C - I

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; 
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; 
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]]; 

Swift - OR

let predicate1:NSPredicate = NSPredicate(format: "X == 1") 
let predicate2:NSPredicate = NSPredicate(format: "Y == 2") 
let predicate:NSPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate1,predicate2]) 

Swift - I

let predicate1:NSPredicate = NSPredicate(format: "X == 1") 
let predicate2:NSPredicate = NSPredicate(format: "Y == 2") 
let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2]) 

Swift 3 - OR

let predicate1 = NSPredicate(format: "X == 1") 
    let predicate2 = NSPredicate(format: "Y == 2") 
    let predicateCompound = NSCompoundPredicate.init(type: .or, subpredicates: [predicate1,predicate2]) 

Swift 3 - I

let predicate1 = NSPredicate(format: "X == 1") 
    let predicate2 = NSPredicate(format: "Y == 2") 
    let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2]) 
+0

Uwielbiam to! Mój kod wygląda o wiele ładniej, jak ten –

+0

Ładny kod ... pracował dla mnie. Wzniesione !!! – NSPratik

Powiązane problemy