Come impostare correttamente un NSPredicate per una relazione to-many quando si utilizzano i dati principali?

Possiedo un modello di dati di base in cui un’ quadro attività include una relazione opzionale to-many ExcludedDays all’entity framework ExcludedDay. Una delle proprietà di ExcludedDay è day, che è un object NSDate. L’ quadro ExcludedDay ha una relazione inversa obbligatoria to-one con l’ quadro Task.

Per recuperare le attività per un giorno specifico, devo assicurarmi che il giorno specificato non appaia come proprietà del giorno di qualsiasi entity framework di ExludedDay.

Ho iniziato a provare

NSPredicate *dayIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"ALL excludedDays.day != %@", today]; 

Tuttavia, nonostante ciò che dice la documentazione, ALL non funziona e l’applicazione lancia un’eccezione: terminando l’app a causa dell’eccezione non rilevata ‘NSInvalidArgumentException’, motivo: ‘predicato non supportato.

Dopo aver pubblicato la stessa domanda in questo forum, sono stato in grado di ideare il seguente predicato con l’aiuto di varie persone:

 NSPredicate * dayIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"[email protected] == 0 || ([email protected] > 0 && NONE excludedDays.day == %@))", today]; 

Mentre questo ha funzionato all’inizio, ho appena scoperto che funziona solo quando l’entity framework ExcludedDay contiene SOLO un giorno. Non appena l’ quadro ExcludedDay contiene più di un giorno per la stessa attività, questo predicato smette di funzionare. Di conseguenza, un’attività viene selezionata per un giorno anche se il giorno appare come un giorno nell’entity framework ExcludedDay, che ovviamente è errata. Il problema non è legato al fatto che il giorno della proprietà sia un object NSDate: sostituendo il giorno con il NSString corrispondente o equivalentemente con un numero intero, ho ancora lo stesso problema e un comportamento errato.

Qual è il modo corretto di implementare il predicato in questo caso? Può essere un bug relativo all’ANY operatore aggregato quando si utilizzano i dati principali? Grazie in anticipo, questo mi sta facendo impazzire.

Si scopre che questo è un altro problema con la documentazione mancante e / o incoerente.

Il predicato corretto in questo caso è il seguente:

 [NSPredicate predicateWithFormat:@"([email protected] == 0) OR (0 == SUBQUERY(excludedOccurrences, $sub, $sub.day == %@)[email protected])", today] 

Nel predicato viene utilizzata una sottoquery per verificare se il numero di Uscite correlate correlate con una data che corrisponde alla data del test è uguale a zero. Tuttavia, la documentazione è fuorviante. Ecco cosa dice la Predicate Programming Guide sull’uso dei predicati insieme alle relazioni to-many.

Utilizzo di predicti con relazioni

Se si utilizza una relazione to-many, la costruzione di un predicato è leggermente diversa. Se si desidera recuperare i reparti in cui almeno uno dei dipendenti ha il nome “Matthew”, ad esempio, si utilizza un operatore ANY come illustrato nell’esempio seguente:

 NSPredicate *predicate = [NSPredicate predicateWithFormat: @"ANY employees.firstName like 'Matthew'"]; 

Se si desidera trovare reparti in cui tutti i dipendenti sono pagati più di un determinato importo, si utilizza un operatore ALL come mostrato nell’esempio seguente:

 float salary = ... ; NSPredicate *predicate = [NSPredicate predicateWithFormat: @"ALL employees.salary > %f", salary]; 

Piuttosto curioso di come risolvere questo problema ho impostato un piccolo progetto e creato il contesto che stai usando.

 NSDate *today = [NSDate date]; NSMutableArray *objects = [NSMutableArray array]; { NSArray *day = [NSArray arrayWithObjects:today, [today dateByAddingTimeInterval:20.0f], nil]; NSDictionary *excludedDay = [NSDictionary dictionaryWithObject:day forKey:@"day"]; NSDictionary *object = [NSDictionary dictionaryWithObject:excludedDay forKey:@"excludedDay"]; [objects addObject:object]; } { NSArray *day = [NSArray arrayWithObjects:[today dateByAddingTimeInterval:20.0f], nil]; NSDictionary *excludedDay = [NSDictionary dictionaryWithObject:day forKey:@"day"]; NSDictionary *object = [NSDictionary dictionaryWithObject:excludedDay forKey:@"excludedDay"]; [objects addObject:object]; } NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE excludedDay.day == %@", today]; NSArray *filtered = [objects filteredArrayUsingPredicate:predicate]; NSLog(@"%@", filtered); 

Questo dà l’object quando:

  1. L’array del giorno è vuoto
  2. L’array del giorno non contiene la data “oggi”

Questo non dà l’object quando:

  1. L’array del giorno contiene il ‘oggi’
    • Non importa quanti oggetti nell’array del giorno sono