web-dev-qa-db-ja.com

NSArrayのNSPredicateを使用して、任意のオブジェクトを検索します

名前、住所、電話番号を持つオブジェクトの配列があります。いいえなど。

名前フィールド、住所フィールドなど、用語の出現を配列で検索できるようにしたい。

私はこのようなことを念頭に置いています:

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
    // Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array


    [self.searchResults removeAllObjects];
    // Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",searchText];
    searchResults = [NSMutableArray arrayWithArray:[contactArray filteredArrayUsingPredicate:predicate]];
}

これにより、「コレクションでin/contains演算子を使用できません」という例外が発生します。

更新。最大3つのフィールドで検索できるようになりました。 4番目を(任意の順序で)追加すると、「フォーマット文字列を解析できません...」という例外が発生します。

述語コードは次のようになりました。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.narrative contains[c] %@ OR SELF.category contains[c] %@ OR SELF.date contains[c] OR SELF.name contains[c] %@", searchText, searchText, searchText, searchText];

     searchResults = [NSMutableArray arrayWithArray:[allDreams filteredArrayUsingPredicate:predicate]];

述語検索フィールドの制限は3つですか?どうすればこれを回避できますか?再度、感謝します。

11
David DelMonte

それらすべてをチェックする述語文字列を使用するだけです。

@"name contains[cd] %@ OR address contains[cd] %@"

いくつでも追加できます。

唯一の欠点は、テストするフィールドごとに同じ検索文字列を追加する必要があることです。これは少し醜いように見える場合があります。

オブジェクトが辞書の場合、サブクエリを使用して、コンパイル時に必ずしも名前を知らなくても、すべての値を真に検索する方法があります。

それはこのように動作します:

@"subquery(self.@allValues, $av, $av contains %@).@count > 0"

ディクショナリオブジェクトに@allValues特殊キー(または必要に応じてメソッド呼び出し)を使用し、それを使用して検索文字列を含む値をフィルタリングします。いずれかが見つかった場合(つまり、カウントが正の場合)、オブジェクトは結果に含まれます。

これにより、辞書に値がある場合は含めたくない値も含めて、すべての値が無差別に検査されることに注意してください。

17
Monolo

あなたの配列項目は純粋な文字列ではないと思いますよね?

配列アイテムにname属性が含まれているとすると(辞書であっても)、次の方法で検索できます。

NSPredicate * predicate =
  [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@ OR name LIKE[cd] %@", searchText, searchText];

ここで、nameSELF.name


[〜#〜] here [〜#〜] は公式文書です。

4
Kjuly