2009-08-28 18 views
22

Possiedo un modello di dati di base in cui un'entità attività include una relazione opzionale to-many ExcludedDays all'entità ExcludedDay. Una delle proprietà di ExcludedDay è day, che è un oggetto NSDate. L'entità ExcludedDay ha una relazione inversa obbligatoria to-one con l'entità Task.Come configurare correttamente un NSPredicate per una relazione to-many quando si utilizzano i dati principali?

Per recuperare le attività per un giorno specifico, è necessario assicurarsi che il giorno specificato non appaia come proprietà del giorno di qualsiasi entità di ExludedDay.

ho iniziato cercando

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

Tuttavia, nonostante quello che dice la documentazione, ALL non funziona e l'applicazione genera un'eccezione: terminazione app a causa di eccezione non identificata ‘NSInvalidArgumentException’, la ragione: ‘predicato non supportato.

Dopo aver postato la stessa domanda in questo forum, sono stato in grado di elaborare il seguente predicato con l'aiuto di varie persone:

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

Anche se questo ha funzionato in un primo momento, ho appena scoperto che questo funziona solo quando l'entità ExcludedDay contiene SOLO un giorno. Non appena l'entità 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'entità ExcludedDay, che ovviamente è errata. Il problema non è legato al fatto che il giorno della proprietà sia un oggetto 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.

risposta

42

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

la correttezza predicato in questo caso è la seguente:

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

Nel predicato, un subquery viene utilizzata per verificare se il numero di excludedOccurrences collegate con una data corrispondono 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.

Uso predicati con relazioni

Se si utilizza un rapporto a-molti, la costruzione di un predicato è leggermente diverso. Se si vuole prendere Dipartimenti in cui almeno uno dei dipendenti ha il nome "Matteo", per esempio, si utilizza un qualsiasi operatore, come mostrato nel seguente esempio:

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

Se si vuole trovare Dipartimenti in cui tutti i dipendenti sono pagati più di un certo importo, si utilizza un ALL operatore, come mostrato nel seguente esempio:

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

Forse sai come scrivere l'espressione con SUBQUERY con classi NSExpresion e NSComparisonPredicate? Con la tua risposta, ho deciso la mia domanda: http://stackoverflow.com/questions/2006927/whats-better-way-to-build-nspredicate-with-to-many-deep-relationships Grazie – Victor

+1

Grazie mille per questa risposta, davvero utile. – Maria

1

Piuttosto curioso di come risolvere questo problema, ho impostato un piccolo progetto e creato il contesto in uso.

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'oggetto quando:

  1. L'array giorno è vuota
  2. La matrice giorno non contiene la data di 'oggi'

questo non dà l'oggetto quando:

  1. La serie di giorni contiene l' 'oggi'
    • Non importa quanti oggetti nella matrice giorno sono
+1

Purtroppo, questo è un ambiente completamente diverso: mio contesto è basata su core Data e iPhone SDK 3.0 o 3.1. Sembra che il framework Core Data non stia gestendo correttamente i predicati quando si segue una relazione to-many. Ho già segnalato un bug e gli ingegneri Apple ci stanno lavorando, ma ancora nessuna risposta da parte loro. –

+1

Quindi si tratta di un problema inoltrato da Core Data, poiché utilizzando lo stesso predicato ma senza Core Data funziona correttamente (come nel mio tentativo di imitare lo stesso contesto (basato su Foumdation)) – Joost

+1

mi ha aiutato nel 2011 :) +1 –

Problemi correlati