2012-04-25 8 views
30

Wieder zurück mehr Hilfe benötigen, mit meinem NSPredicates Konstruktion :(Kombination ‚UND‘ und ‚ODER‘ Zustand in NSPredicate

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

SubCategory 
{ 
    name:string 
    numbervalue:NSNumber 
} 

Ich würde gerne wissen, wie ein Prädikat mit zu schaffen und und OR .

zum Beispiel würde ich mit einem numbervalue von „WertA“ OR „WertB“.

hat jede Kategorie mit dem Namen zurückkehren möge == „category_name“, das eine Unterkategorie auch 0

Ich habe jede mögliche Kombination von Prädikat Konstruktoren ausprobiert, aber ich kann es einfach nicht zum Laufen bringen.

Dies ist mein bisher bester Versuch.

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

bearbeiten 1

Zweiter Versuch. Die Filterung des 'numbervalue' funktioniert immer noch nicht.

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]; 

bearbeiten 2

ich Filterung nur von numberValue versucht haben und haben den Namen aus alltogether links.

1) die Verwendung führt dazu, dass der gesamte Satz zurückgegeben wird, selbst wenn nur 1 Element im Satz den Wert hat.

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

2) Daraus ergibt sich die gleiche Problem verwenden, wobei jedes Element in dem Satz zurückgeführt, auch wenn nur 1 von ihnen übereinstimmt.

Auch die einfachste Version führt zu dem gleichen Problem .... Ich habe das früher nicht bemerkt.

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

Also ich denke, ich habe mein Problem eingegrenzt.

Kategorie ist eine Entität. Unterkategorie ist eine Entität.

Kategorie hat eine Eins-zu-viele-Beziehung mit Unterkategorie und wird als NSSet der Unterkategorie dargestellt.

Jede Unterkategorie hat ein Attribut mit dem Namen numbervalue.

bearbeiten 3

Um zu testen, I 2 categorys haben. Beide Kategorien haben 10 Subs mit jeweils einem Zahlenwert von 1 -10;

Mit diesem Code werden beide Kategorien zusammen mit allen 10 Subs für jedes zurückgegeben.

Das erwartete Ergebnis ist, dass beide Kategorien zurückgegeben werden, jede mit nur 2 Subs.

Ich habe alle meine Objekte verfolgt und die Daten sind korrekt. Das Problem ist, dass ich keine Kategorie zurückgeben kann, die Subs gefiltert hat.

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

Haben Sie 'NSCompoundPredicate' überprüft? Es sollte dir helfen. Versuchen Sie es auch mit '... AND (ANY subs.numberValue IN% @)", @ "fooName", numArray' – Eimantas

+0

danke für die Tipps – dubbeat

+0

Verwenden Sie $ x.numbervalue und nicht $ numbervalue. Versuchen Sie dann, den Cache auf Null zu setzen Zuerst und sehen Sie das Ergebnis. –

Antwort

32

Ich werde Folgendes mit einer SUBQUERY tun.

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

Versuchen Sie es und lassen Sie mich wissen. Eine andere Lösung könnte sein, die gesamte Sammlung subs zu erfassen und dann den abgerufenen Satz mit einem Prädikat zu filtern, um zu prüfen, ob die Elemente für oder value2 übereinstimmen.

Ich hoffe, es hilft.

bearbeiten

Wenn Sie folgen Eimantas Vorschlag sicherstellen, dass die richtige Array zu erstellen:

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

was scheint zu passieren ist, wenn eine Sammlung von Subs einen Zahlenwert von 90 zum Beispiel hat, aber der Rest ist sagen 0, wird die gesamte Sammlung von Subs immer noch – dubbeat

+0

versucht zu verwenden Nur * (SUBQUERY (subs, $ x, $ x.numbervalue ==% @ oder $ x.numbervalue ==% @). @ count> 0) * im Prädikat und das Array mit einem zusätzlichen Prädikat filtern, um das zu finden Name. –

+0

Welches Ergebnis erhalten Sie nur mit der SUBQUERY? –

49

Zusätzlich zu @ Stuart's Antwort können Sie NSCompoundPredicate für Ihre ODER & AND Operationen wie diese verwenden.

Obj-C - OR

// OR Condition // 

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

Obj-C - UND

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 - UND

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 - UND

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

Liebe es! Mein Code sieht viel besser aus wie dieser –

+0

Netter Code ... arbeitete für mich. Upvoted !!! – NSPratik

Verwandte Themen