NSPredicateEditorRowTemplate:如何填充右侧弹出窗口

mar*_*kjs 2 cocoa nspredicateeditor nspredicate nsexpression

我正在尝试NSPredicateEditorRowTemplate从实体Foo生成一个左侧有许多属性名称的属性,其中包括属性bar。当用户选择“ bar ”时,右侧应成为包含“ bar ”所有值的弹出窗口。

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

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

编辑

阅读了大量相关问答,包括Xcode 4 中的 NSPredicateEditor以及@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 == ''"];
Run Code Online (Sandbox Code Playgroud)

我已经看到了一些办法,使基本NSPredicateEditor出现(至少与复合线),但在我看来,必须有一种优雅的方式来做到这一点,它的方式意味着要做。但是找不到,有人可以帮我解决这个问题吗?

Dav*_*ong 5

有些可能会说,事情是这样的意思做的是在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];
Run Code Online (Sandbox Code Playgroud)

当然,这只是为了创建行模板而进行的大量输入。我明白那个。我只是认为它也非常明确且易于调试。话虽如此,您也可以在 Interface Builder 中配置完全相同的内容。为此,请NSPredicateEditor在您的 xib 中放入一个,并为其提供 3 行模板。您可以单独保留复合行模板,但您将更改其他两个配置如下:

对于 " bar" 模板:

“条”行模板配置

对于 " baz" 模板:

“baz”行模板配置

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

带有谓词编​​辑器的窗口

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


编辑以回答评论问题

modifier这些选择器的位对应于NSComparisonPredicateModifer创建的NSComparisonPredicate. 共有三种修饰符:Direct、Any 和 All。

@"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
Run Code Online (Sandbox Code Playgroud)

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

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

  • @markjs 检查 IB 中的“可以删除所有行”复选框(或 `setCanRemoveAllRows:`)。您希望它是“NO”,此时如果只剩下一行,编辑器将删除`-` 按钮(如果您允许复合,它将是复合行)。 (2认同)