cocoa - NSPredicateEditorRowTemplate : how to to populate right side popup

标签 cocoa nspredicate nspredicateeditor nsexpression

我正在尝试生成一个 NSPredicateEditorRowTemplate,其左侧有多个来自实体 Foo 的属性名称,其中有属性 bar。当用户选择“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 == ''"];

我已经看到了几种使基本 NSPredicateEditor 出现的方法(至少有复合行),但在我看来,必须有一种优雅的方法来做到这一点,就像它的意思一样 待完成。但找不到,有人可以帮助我吗?

最佳答案

有些人可能会认为它的实现方式是在 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 中配置完全相同的东西。为此,请将 NSPredicateEditor 放入您的 xib 中,并为其提供 3 行模板。您可以保留复合行模板,但您可以将另外两个模板更改为如下配置:

对于“bar”模板:

"Bar" row template configuration

对于“baz”模板:

"Baz" row template configuration

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

Window with predicate editor

如果您想要执行更高级的操作,例如创建自定义行模板,或使用数据模型中的内容填充允许的常量值列表,那么您必须直接在代码中进行配置。

<小时/>

编辑以回答评论问题

这些选择器的修饰符位对应于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

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

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

关于cocoa - NSPredicateEditorRowTemplate : how to to populate right side popup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18209138/

相关文章:

objective-c - 如何在基于文档的应用程序的文档窗口 Controller 中接收菜单项事件?

ios - NSPredicate可能匹配多个属性

ios - 如何为 segue 引用 NSPredicate 的 "%@"?

macos - 为什么 NSPredicateEditor 会自动本地化一些表达式字符串?如何禁用?

iphone - NSPredicate:如何在过滤器中插入特殊字符(@$&)

macos - NSWindow 显示的建议

ios - 为 iOS 和 Mac OS X 编写应用程序的最佳 C 类型策略

objective-c - 如何使网页 View 的一部分稍微半透明?

objective-c - 如何通过键中的子字符串过滤 NSDictionary?

cocoa - 使用 NSPredicateEditor 强制显示复合行