26

Core Data と NSManagedObjects を使用して UITableView を設定するアプリで遊んでいます。私のアプリケーションには、 という名前のクラスが 1 つしかありませんEvent。に次のカスタム インスタンス メソッドを作成しましたEvent

- (BOOL)isExpired {
    return ([[self.endOn dateAtEndOfDay] timeIntervalSinceNow] < 0);
}

UITableViewオブジェクトを表示するEventオブジェクトを、有効期限が切れたイベントのみに制限したいと思います。つまり、isExpired戻りますYES。に を追加して、これを実行しようとしNSPredicateましたNSFetchRequest:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * bindings) {return([evaluatedObject isExpired]);}];
[fetchRequest setPredicate:predicate];

しかし、エラーが発生します: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Problem with subpredicate BLOCKPREDICATE(0x272ac)' ***. これは、NSFetchRequest でブロック述語を使用できないということですか? それとも、不適切に構築しただけですか?

ありがとうございました!

4

2 に答える 2

24

そのため、元の投稿へのコメントで、これは SQLite ストアがブロック述語と互換性がないことが原因である可能性が高いことを立証したようです。これは、Core Data がこれらを SQL に変換してストアで実行できないためです (JoostK に感謝します)。

これを克服するには、いくつかの方法があります。

  • エンティティの終了日が通常の属性である場合、コア データが SQL 句に変換できるはずのブロック述語ではなく、述語フォーマット文字列として有効期限制約を表現できる場合があります。
  • 上記が可能な場合は、フェッチ リクエスト テンプレートを使用して期限切れのアイテムを取得することをお勧めします。$NOWただし、現在の日付にアクセスできるようにするには、置換変数を渡す必要があります。これには、述語テンプレートがモデル エディターに表示されるという利点があります。
  • ただし、どちらのアプローチにも、既存の機能 (つまり、isExpiredメソッド) が重複するという欠点があります。したがって、別の方法は、最初に有効期限の状態に関係なくすべての資格のあるエンティティをフェッチし、次に結果のエンティティ セットに対して専用のフィルタリング ステップを実行して、有効期限が切れていないエンティティを除外することです。その時点までにストアから完全に復活しているので、これにはブロック述語を使用できるはずです。
于 2010-08-23T07:18:38.307 に答える
7

述語を指定せずに通常のフェッチ リクエストを実行し、その後、結果の配列をフィルタリングできます。

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

if (!allEvents) { // do error handling here
}

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];
于 2011-06-15T11:37:48.990 に答える