web-dev-qa-db-fra.com

Core Data, NSPredicate et clé to-many

J'ai un modèle de données de base dans lequel une entité de tâche inclut une relation facultative à plusieurs exclusOccurrences. L'une des propriétés de exclusOccurrences est start, qui est un objet NSDate. L'entité ExcludedOccurrence a une relation inversée obligatoire à une avec l'entité Task.

Afin de récupérer des tâches pour un jour spécifié, je dois m'assurer que le jour spécifié n'apparaît pas en tant que propriété de début d'une entité ExcludedOccurrence. L'un des sous-prédicats que j'essaie d'utiliser est donc

NSPredicate *occurrenceIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"(ALL excludedOccurrences.start != %@))", today];

où today est un objet NSDate pour aujourd'hui comprenant uniquement les composants jour, mois et année. Toutes les propriétés de début des occurrences exclues incluent également uniquement les composants jour, mois et année.

Bien que cela devrait fonctionner correctement, au moins en lisant la documentation de Core Data et NSPredicate, j'obtiens le message d'erreur suivant:

Arrêt de l'application en raison d'une exception non interceptée 'NSInvalidArgumentException', raison: 'Prédicat non pris en charge

Si j'utilise le prédicat équivalent

NSPredicate *occurrenceIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"!(ANY excludedOccurrences.start == %@))", today];

aucune exception n'est levée, mais le code ne fonctionne pas comme prévu: l'occurrence d'aujourd'hui, qui ne doit pas être exclue, est à la place exclue.

Je ne sais pas aussi comment tester le cas excluOccurrences == nil: le prédicat suivant

NSPredicate *nilPredicate = [NSPredicate predicateWithFormat: @"(excludedOccurrences == nil)"];

provoque à l'exécution l'exception

clé to-many non autorisée ici

Cependant, étant donné que la relation exclueOccurrences est facultative, je dois également tester si elle est nulle.

Comment gérer cela? Merci d'avance.

42
Massimo Cafaro

avec l'aide de vous tous, j'ai finalement réussi à déterminer le bon prédicat pour mon scénario. Il semble qu'un objet NSDate soit traité comme un double, cependant, le double n'est jamais quelque chose comme 3.7, c'est toujours comme 3.0 Par conséquent, le prédicat suivant fonctionne correctement dans mes tests:

NSPredicate *occurrenceIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"(excludedOccurrences.@count == 0 || (excludedOccurrences.@count > 0 && NONE excludedOccurrences.start == %@))",thisDate];

où thisDate est un objet NSDate contenant uniquement les composants jour, mois et année (comme dans le cas de la propriété start de l'entité ExcludedOccurrence.

Le test d'une relation vide se fait essentiellement à l'aide de l'opérateur d'agrégation @count, comme suggéré par certains chez Apple.

Encore une fois, merci beaucoup pour votre aide. J'observe toujours que la documentation est imparfaite en plusieurs parties (en particulier là où il est dit que TOUT fonctionne bien alors qu'au lieu de cela, cela ne fonctionne pas du tout).

28
Massimo Cafaro

Pour tester une relation vide, vous devez comparer le nombre de clés to-many à zéro.

[NSPredicate predicateWithFormat:@"excludedOccurrences.@count == 0"];

En ce qui concerne vos sous-prédicats, sachez que vous ne pouvez avoir que l'un des modificateurs ALL ou ANY dans votre prédicat final, bien que vous puissiez utiliser ce modificateur plusieurs fois dans le prédicat.

Pas OK: ANY foo.bar = 1 AND ALL foo.baz = 2
OK:ANY foo.bar = 1 AND !(ANY foo.baz != 2)

110
Ashley Clark

Donc, pour tester une relation non vide, cela fonctionne réellement:

[NSPredicate predicateWithFormat:@"relationship.@count != 0"]

La solution proposée par Ashley Clark se bloque pour moi en donnant "la clé à plusieurs n'est pas autorisée ici"

8
Simon Woodside

Et dans Swift 2, quelque chose comme:

request.predicate = NSPredicate(format: " relationship.@count != 0")
4
Steve