我试图生成一个NSPredicateEditorRowTemplate,它在左侧具有来自实体Foo的许多属性名称,其中是属性栏。当用户选择“ bar”时,右侧应弹出,其中包含“ bar”的所有值。

如何最好地填充右侧弹出窗口? bar的所有唯一值都存储在NSMutableArray中,因此也许我可以使用KVO在数组更改时更改行模板。

有没有一种方法可以使用代码轻松更改NSPredicateEditor行右侧弹出窗口中的值?我可以在IB中输入一些静态值,但是在这种情况下不会这样做。

编辑

阅读了很多相关的问答,包括NSPredicateEditor in Xcode 4以及@Dave DeLong对它的出色回答,我认为可以像这样完成很多工作:

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 == ''"];


我已经看到了几种使基本的N​​SPredicateEditor出现的方法(至少带有复合线),但是在我看来,必须有一种优雅的方法来完成该工作,而这本来是必须的。虽然找不到,但是有人可以帮助我吗?

最佳答案

有人可能会争辩说,它的完成方式是在Interface Builder中。如果您熟悉行模板的工作方式,如何组合等,那可能会很好。就个人而言,我更喜欢以编程方式创建,因为我可以明确地了解行模板的功能。

让我们来看一个如何将它们一起使用的示例,然后您可以决定哪种方法最适合您:


您有一个具有两个NSString属性的对象:barbaz
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中配置相同的东西。为此,在您的xib中放置一个NSPredicateEditor,并为其提供3行模板。您将不理会“ Compound”行模板,但将其他两个更改为如下配置:

对于“ bar”模板:



对于“ baz”模板:



如果将这些屏幕截图与上面的代码进行比较,(希望)很容易看到一个屏幕如何映射到另一个屏幕。使用这样配置的行模板,IB还将在您的窗口中显示谓词编辑器:



如果您想做更高级的事情,例如创建自定义行模板,或用数据模型中的内容填充允许的常量值列表,那么您将不得不执行代码中的配置。



编辑以回答评论问题

这些选择器的modifier位对应于创建的NSComparisonPredicateModiferNSComparisonPredicate。共有三个修饰符:“直接”,“任意”和“全部”。

@"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


在这三个示例中,它们都是比较谓词(因为它们具有左侧,运算符和右侧),但是使用“ ANY”或“ ALL”会影响左侧的解释方式。如果存在任何一个,则谓词期望左侧评估一组可能性。

使用“直接”选项(或0)基本上意味着您将进行一对一的比较。

09-25 18:00