web-dev-qa-db-ja.com

コアデータ、NSPredicateおよび多対多キー

タスクエンティティにオプションの多対多のリレーションシップexcludeOccurrencesが含まれるコアデータモデルがあります。 excludeOccurrencesのプロパティの1つは、NSDateオブジェクトであるstartです。 ExcludedOccurrenceエンティティには、Taskエンティティと逆の必須の1対1の関係があります。

指定した日のタスクを取得するには、指定した日がExcludedOccurrenceエンティティの開始プロパティとして表示されないようにする必要があります。したがって、私が使用しようとしているサブ述語の1つは、

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

ここで、todayは、日、月、年のコンポーネントのみを含む今日のNSDateオブジェクトです。除外されたすべてのオカレンス開始プロパティには、日、月、年のコンポーネントのみが含まれています。

これは問題ないはずですが、少なくともCore DataとNSPredicateのドキュメントを読んでいると、次のエラーメッセージが表示されます。

キャッチされなかった例外「NSInvalidArgumentException」によるアプリの終了、理由:「サポートされていない述語

同等の述語を使用する場合

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

例外はスローされませんが、コードは期待どおりに動作しません。除外すべきではない今日の発生が代わりに除外されます。

また、excludeOccurrences == nilの場合のテスト方法もわかりません。次の述語

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

実行時に例外を引き起こします

多対多のキーはここでは許可されていません

ただし、excludeOccurrences関係はオプションであるため、nilかどうかもテストする必要があります。

どうすればこれに対処できますか?前もって感謝します。

42
Massimo Cafaro

皆さんの助けを借りて、ようやく私のシナリオに適した述語を決定することができました。 NSDateオブジェクトはdoubleとして処理されるように見えますが、doubleは3.7のようにはならず、常に3.0のようになります。したがって、次の述語はテストで正しく機能します。

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

ここで、thisDateは、日、月、年のコンポーネントのみを含むNSDateオブジェクトです(ExcludedOccurrenceエンティティのstartプロパティの場合と同様)。

空の関係のテストは、基本的に、@ count集計演算子を使用して行われます。これは、Appleの一部の人々が示唆しています。

繰り返しますが、どうぞよろしくお願いいたします。私はまだドキュメントにいくつかの部分に欠陥があることを観察します(特に、ALLは正常に機能するが、まったく機能しないと述べている場合)。

28
Massimo Cafaro

空の関係をテストするには、多対多キーの数をゼロと比較する必要があります。

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

サブ述語については、最後の述語でALLまたはANY修飾子のいずれか1つしか使用できないことに注意してください。ただし、その修飾子は述語全体で複数回使用できます。

Not OK:_ANY foo.bar = 1 AND ALL foo.baz = 2_
OK:ANY foo.bar = 1 AND !(ANY foo.baz != 2)

110
Ashley Clark

したがって、空でない関係をテストするために、これは実際に機能します。

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

アシュリークラークのソリューションは、「ここでは多対多のキーは許可されていません」と言ってクラッシュします。

8
Simon Woodside

そしてSwift 2のように:

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