我正在尝试生成一个 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
属性的对象: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 行模板。您可以保留复合行模板,但您可以将另外两个模板更改为如下配置:
对于“bar
”模板:
对于“baz
”模板:
如果将这些屏幕截图与上面的代码进行比较,应该(希望)很容易看出一个屏幕截图如何映射到另一个屏幕截图。通过像这样配置的行模板,IB 还会在窗口中显示谓词编辑器:
如果您想要执行更高级的操作,例如创建自定义行模板,或使用数据模型中的内容填充允许的常量值列表,那么您必须直接在代码中进行配置。
<小时/>编辑以回答评论问题
这些选择器的修饰符
位对应于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/