NSPredicate 全構文解説

  • 377
    いいね
  • 0
    コメント

NSPredicateで使用できる全構文の解説です。

確認に使用したサンプルコードはこちらです。

NSPredicate Programming Guide - Predicate Format String Syntaxに記載しているのは全て取り上げていますが、SUBQUERYがNSExpressionに書いてあったりしたからまだ他にもあるのかもしれません。

あと@を指定して使用する関数のドキュメントが見つからなかった・・・ドキュメントが乱雑し整理されていない感じがしました。

関連キーワード: BNF, NSExpression

注意: SQLと同じ用語には注意が必要です。例えばANYはSQLのANYとは異なります。

リテラル

%@

文字列として扱われる(ダブルクォーテーションで囲われる)

%@
NSString *attributeValue = @"Anne";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstName LIKE %@", attributeValue];

// predicate: firstName LIKE "Anne"

%K

動的プロパティとして扱われる(ダブルクォーテーションで囲われない)

%K
NSString *attributeName = @"firstName";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K LIKE \'Anne\'", attributeName];

// predicate: firstName LIKE "Anne"

{ 'comma', 'separated', 'literal', 'array' }

カンマで区切られたリテラル配列の表記

SELF

評価されるオブジェクト自身

FALSE, NO

false

TRUE, YES

true

NULL, NIL

null

"text" , 'text'

文字列。"text"と'text'は同じ。混在時に注意("a'b'c" は a, 'b', c と相当)

1, 27, 2.71828, 19.75

整数と固定小数点表記

9.2e-5

累乗と浮動小数点表記

0x

16進数

0o

8進数

0b

2進数

比較

=, ==

左辺値と右辺値が等しい

>=, =>

左辺値は右辺値以上

<=, =<

左辺値は右辺値以下

>

左辺値は右辺値を超える

<

左辺値は右辺値未満

!=, <>

左辺値と右辺値は等しくない

BETWEEN

array[0]以上、array[1]以下

BETWEEN
NSPredicate *betweenPredicate = [NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];
// ((1 <= attributeValue ) && ( attributeValue <= 10))

BOOL値

TRUEPREDICATE

常にTRUEで評価される

TRUEPREDICATE
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
NSLog(@"evaluate: %@", @([predicate evaluateWithObject:[self users]]));
// evaluate: 1

NSLog(@"all users: %@", [[self users] filteredArrayUsingPredicate:predicate]);
/*
all users: (
    "firstName: Herbert, lastName: Korberg, age: 20, gender: 1",
    "firstName: Anne, lastName: Nordenskiold, age: 24, gender: 0",
    "firstName: Juanito, lastName: Suela, age: 35, gender: 1",
    "firstName: Rebecca, lastName: Vinci, age: 14, gender: 0",
    "firstName: %@, lastName: Vinci, age: 14, gender: 0"
)
*/

FALSEPREDICATE

常にFALSEで評価される

FALSEPREDICATE
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"FALSEPREDICATE"];
NSLog(@"evaluate: %@", @([predicate evaluateWithObject:[self users]]));
// evaluate: 0

NSLog(@"all users: %@", [[self users] filteredArrayUsingPredicate:predicate]);
/*
all users: (
)
*/

論理演算

AND, &&

論理積

OR, ||

論理和

NOT, !

否定

文字列の比較

BEGINSWITH

右辺値から始まる文字列か

CONTAINS

右辺値が含まれているか

ENDSWITH

右辺値で終わる文字列か

LIKE

右辺値と完全一致するか
ワイルドカードとして「」「?」が使用可能(は0文字以上一致、?は1文字以上一致)

MATCHES

正規表現(ICU v3)

文字列比較のオプション

c

大文字・小文字の区別なし(case-insensitive)

[c]
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstName LIKE[c] \'anne\'", attributeName];
NSLog(@"%@", [[self users] filteredArrayUsingPredicate:predicate]);
/*
(
    "firstName: Anne, lastName: Nordenskiold, age: 24, gender: 0"
)
*/

d

ダイアクリティカルマークを無視する(diacritic-insensitive)

[d]
NSPredicate *pridicate = [NSPredicate predicateWithFormat:@"firstName LIKE[d] \'Marka\'"];
NSLog(@"%@", [[self users] filteredArrayUsingPredicate:pridicate]);
/*
(
    "firstName: Márkä, lastName: Chèrêpkõv, age: 50, gender: 0"
)
*/

集計操作

比較で左辺値が多の要素の場合、ANY, ALL, NONEのいずれかを指定する必要がある。

ANY, SOME

いずれかの要素が条件と一致する

ANY,SOME
// 1999年以降の書籍を1つ以上持っているか
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY books.year > 1999"];
NSLog(@"%@", [[self library].authors filteredArrayUsingPredicate:predicate]);
/*
(
    "<name: Herbert; books: {(<title: AAA; year: 1990>, <title: BBB; year: 2000>, <title: CCC; year: 2010>)}>",
    "<name: Juanito; books: {(<title: EEE; year: 2001>)}>"
)
*/

※ authorなので持っているかではなくて書いているかだけど意味が伝わりやすいように変更してる

ALL

全ての要素が条件と一致する

ALL
// 1999年以降の書籍のみ持っているか
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL books.year > 1999"];
NSLog(@"%@", [[self library].authors filteredArrayUsingPredicate:predicate]);
/*
(
    "<name: Juanito; books: {(<title: EEE; year: 2001>)}>"
)
*/

NONE

全ての要素が条件と一致しない

NONE
// 1999年以降の書籍を1つも持っていない
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE books.year > 1999"];
NSLog(@"%@", [[self library].authors filteredArrayUsingPredicate:predicate]);
/*
(
    "<name: Anne; books: {(<title: DDD; year: 1991>)}>"
)
*/

IN

いずれかの条件と一致する(SQLのIN相当)

IN
// 名前がAnneまたはJuanitoか
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name IN %@", @[@"Anne", @"Juanito"]];
NSArray *filterdArray = [[self library].authors filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filterdArray);
/*
(
    "<name: Anne; books: {(<title: DDD; year: 1991>)}>",
    "<name: Juanito; books: {(<title: EEE; year: 2001>)}>"
)
*/

SUBQUERY

サブクエリ

フォーマット
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(books, $s, $s.year > 2000 AND $s.year < 2010).@count > 0"];
NSArray *filterdArray = [[self library].authors filteredArrayUsingPredicate:predicate];
NSLog(@"%s; %@", __func__, filterdArray);
/*
(
    "<name: Juanito; books: {(<title: EEE; year: 2001>)}>"
)
*/

2次元配列の条件一致

array[index]

配列の配列でindexの要素らが条件と一致

array[index]
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[1] = '2-B'"];
NSArray *filterdArray = [[self schoolClasses] filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filterdArray);
/*
(
        (
        "2-A",
        "2-B"
    )
)
*/

array[FIRST]

配列の配列で1番目の要素らが条件と一致

array[FIRST]
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[FIRST] = '1-A'"];
NSArray *filterdArray = [[self schoolClasses] filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filterdArray);
/*
(
        (
        "1-A",
        "1-B",
        "1-C"
    )
)
*/

array[LAST]

配列の配列で最後の要素らが条件と一致

array[LAST]
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[LAST] = '1-C'"];
NSArray *filterdArray = [[self schoolClasses] filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filterdArray);
/*
(
        (
        "1-A",
        "1-B",
        "1-C"
    )
)
*/

array[SIZE]

配列の配列でサイズが条件と一致するか

array[SIZE]
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[SIZE] = 2"];
NSArray *filterdArray = [[self schoolClasses] filteredArrayUsingPredicate:predicate];
/*
(
        (
        "2-A",
        "2-B"
    )
)
*/

識別子

C言語の識別子

#symbol

予約語のエスケープ

[\]{octaldigit}{3}

8進数のエスケープ(\)

[\][xX]{hexdigit}{2}

16進数のエスケープ(\x, \X)

[\][uU]{hexdigit}{4}

Unicodeのエスケープ(\u, \U)

予約語

AND, OR, IN, NOT, ALL, ANY, SOME, NONE, LIKE, CASEINSENSITIVE, CI, MATCHES, CONTAINS, BEGINSWITH, ENDSWITH, BETWEEN, NULL, NIL, SELF, TRUE, YES, FALSE, NO, FIRST, LAST, SIZE, ANYKEY, SUBQUERY, CAST, TRUEPREDICATE, FALSEPREDICATE

参考サイト

Cocoaの日々 - [Mac][iOS] NSPredicate - 1対多関連のエンティティの検索条件見本