2

NSPredicateEditorRowTemplate左側にエンティティFooからのプロパティ名がいくつかあり、その中にプロパティbarがあるものを生成しようとしています。ユーザーが「bar」を選択すると、右側が「bar」のすべての値を含むポップアップになるはずです。

右側のポップアップに最適に入力するにはどうすればよいですか? barのすべての一意の値はに格納されるNSMutableArrayため、おそらく KVO を使用して、配列が変更されたときに行テンプレートを変更できます。

コードを使用して右側のポップアップの値をNSPredicateEditor連続して簡単に変更する方法はありますか? IB にいくつかの静的な値を入力することはできますが、この状況ではそれができません。

編集

Xcode 4の NSPredicateEditor や @Dave DeLong による優れた回答など、関連する Q&A をかなり読んだので、かなりの作業を次のように行うことができると思います。

NSArray *leftexp = @[[NSExpression expressionForKeyPath:@"name"],[NSExpression expressionForKeyPath:@"married"]];
NSArray *rightexp = @[[NSExpression expressionWithFormat:@"One"],[NSExpression expressionWithFormat:@"Two"]];
NSPredicateEditorRowTemplate *template = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:leftexp rightExpressions:rightexp modifier:NSDirectPredicateModifier operators:@[@(NSEqualToPredicateOperatorType)] options:0];

NSPredicateEditorRowTemplate *compound = [[NSPredicateEditorRowTemplate alloc] initWithCompoundTypes:@[@(NSOrPredicateType)]];

[self.predicateEditor setRowTemplates:@[template,compound]];
NSEntityDescription *description = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
self.predicate = [NSPredicate predicateWithFormat:@"name == ''"];

基本的な NSPredicateEditor を表示する方法をいくつか見てきました (少なくとも複合行を使用) 。それを見つけることができませんが、誰かがこれと一緒に私を助けることができますか?

4

3 に答える 3

5

おそらく、それが意図されている方法はInterface Builderであると主張する人もいるでしょう。行テンプレートがどのように機能するか、それらがどのように結合されるかなどに精通している場合は、おそらくそれで問題ありません。個人的には、行テンプレートがどのように機能するかを明示できるため、プログラムで作成することを好みます。

これらすべてがどのように連携するかの例を見てみましょう。その後、どのアプローチが最適かを判断できます。

  • NSString次の 2 つのプロパティを持つオブジェクトがありbarます。baz
  • bar特定の数の可能な値のみを持つことができます。これを@"Bar1"@"Bar2"、および と呼びます@"Bar3"
  • baz任意のNSString値にすることができます。

これを念頭に置いて、プログラムでそれを作成する方法は次のとおりです。

// these defines are for brevity on the web page; please don't actually do this
#define NSPERT NSPredicateEditorRowTemplate
#define KP(_kp) [NSExpression expressionForKeyPath:(_kp)]
#define CV(_cv) [NSExpression expressionForConstantValue:(_cv)]

NSPERT *compound = [[NSPERT alloc] initWithCompoundTypes:@[@(NSAndPredicateType), 
                                                           @(NSOrPredicateType), 
                                                           @(NSNotPredicateType)]];

NSPERT *bar = [[NSPERT alloc] initWithLeftExpressions:@[KP(@"bar")] 
                                     rightExpressions:@[CV(@"Bar1"), CV(@"Bar2"), CV(@"Bar3")] 
                                             modifier:NSDirectPredicateModifier 
                                            operators:@[@(NSEqualToPredicateOperatorType), 
                                                        @(NSNotEqualToPredicateOperatorType)] 
                                              options:0];

NSPERT *baz = [[NSPERT alloc] initWithLeftExpressions:@[KP(@"baz")] 
                         rightExpressionAttributeType:NSStringAttributeType 
                                             modifier:NSDirectPredicateModifier 
                                            operators:@[@(NSEqualToPredicateOperatorType),
                                                        @(NSNotEqualToPredicateOperatorType)]
                                              options:0];

NSArray *templates = @[compound, bar, baz];
[self.myPredicateEditor setRowTemplates:templates];

確かに、これは行テンプレートを作成するためだけに大量の入力を行います。という事は承知しています。また、非常に明示的でデバッグが簡単だと思います。そうは言っても、Interface Builder でまったく同じことを構成することもできます。これを行うにはNSPredicateEditor、xib に を入れ、3 行のテンプレートを指定します。複合行テンプレートはそのままにしておきますが、他の 2 つは次のように構成するように変更します。

" bar" テンプレートの場合:

" baz" テンプレートの場合:

これらのスクリーンショットを上記のコードと比較すると、(願わくば) 一方が他方にどのようにマップされるかを簡単に確認できるはずです。行テンプレートをこのように構成すると、IB はウィンドウに述語エディターも表示します。

述語エディターのあるウィンドウ

カスタム行テンプレートを作成したり、データ モデルから何かを使用して許可された定数値のリストを作成したりするなど、より高度なことを行う場合は、コードで構成を行う必要があります。


編集してコメントの質問に答える

modifierこれらのセレクターのビットはNSComparisonPredicateModifer、作成された の に対応しNSComparisonPredicateます。修飾子には、Direct、Any、および All の 3 つがあります。

@"bar = 'Bar1'";
  ^ No modifier means this is NSDirectPredicateModifier

@"ANY user.userName = 'markjs'";
  ^~~ use of "ANY" keyword means this is NSAnyPredicateModifier

@"ALL user.age < 42";
  ^~~ use of "ALL" keyword means this is NSAllPredicateModifier

これらの 3 つの例では、すべて比較述部 (左辺、演算子、および右辺があるため) ですが、「ANY」または「ALL」の使用は、左辺の解釈方法に影響します。いずれかが存在する場合、述語は左側が可能性のコレクションに評価されることを期待しています。

「直接」オプション (または0) を使用することは、基本的に、1 対 1 の比較を行うことを意味します。

于 2013-08-14T20:52:31.267 に答える
3

NSPredicateEditorを複合行 (NOT、AND、OR) で埋め、1 つの行を単純な述語で埋めるための鍵は、複合と通常の述語の両方を含むで呼び出しをNSPredicateEditor受け取る必要があることです。次に、 を使用して、その述語を副述語との複合述語に設定する必要があります。-setRowTemplates:NSArray-andPredicateWithSubpredicates:

これは私にとってはうまくいきました:

NSArray *leftexp = @[[NSExpression expressionForKeyPath:@"name"]];
NSArray *rightexp = @[[NSExpression expressionForConstantValue:@"A"],[NSExpression expressionForConstantValue:@"B"],[NSExpression expressionForConstantValue:@"C"]];
NSPredicateEditorRowTemplate *template = [[NSPredicateEditorRowTemplate alloc] \
          initWithLeftExpressions:leftexp
          rightExpressions:rightexp
          modifier:NSDirectPredicateModifier
          operators:@[@(NSEqualToPredicateOperatorType)]
          options:0];
NSPredicateEditorRowTemplate *compound = [[NSPredicateEditorRowTemplate alloc] initWithCompoundTypes:@[@(NSAndPredicateType),@(NSOrPredicateType),@(NSNotPredicateType)]];
NSMutableArray *templates = [NSMutableArray arrayWithObject:compound];
[templates addObject:template];
[self.predicateEditor setRowTemplates:templates];

NSPredicate *p = [NSPredicate predicateWithFormat:@"name == 'A'"];
self.predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:p]];
于 2013-08-14T20:48:36.940 に答える