我有一个谓词编辑器,模板是通过以下方式生成的:
NSArray * test = [NSArray arrayWithObjects:
[NSExpression expressionForKeyPath: @"Abc"],
[NSExpression expressionForKeyPath: @"Def"],
nil];
NSPredicateEditorRowTemplate * template = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions: test
rightExpressionAttributeType: NSStringAttributeType
modifier: NSDirectPredicateModifier
operators: [NSArray arrayWithObject:
[NSNumber numberWithUnsignedInteger:NSContainsPredicateOperatorType]]
options:(NSCaseInsensitivePredicateOption|NSDiacriticInsensitivePredicateOption)];
所以如果我填写这样的谓词编辑器:
当我退出生成的谓词时,我得到:
Abc CONTAINS[cd] "abc" OR Def CONTAINS[cd] "def"
我想知道的是,如果我能以某种方式让谓词编辑器模板显示与生成的谓词中设置的值不同。
EX:我希望输出谓词具有:
Field1 CONTAINS[cd] "abc" OR Field2 CONTAINS[cd] "def"
即使编辑器仍然显示abc
和def
作为字段。这可能吗?
答案 0 :(得分:10)
是的,你可以这样做。
您希望左表达式数组是最终谓词中的实际keyPath。在您的情况下,"Field1"
和"Field2"
。
至于在弹出窗口中显示不同的值,这里有一个令人费解的概念:
您要将谓词编辑器本地化为英语。
有两种方法可以做到这一点。
NSDictionary
使用.strings文件
在您的来源中,您可以在评论中包含以下内容:
// NSLocalizedStringFromTable(@"%[Field1,Field2]@ %[contains]@ %@", @"PredicateEditor", @"")
当您在源代码上运行genstrings
时,这将生成一个PredicateEditor.strings
文件,其中包含以下条目:
"%[Field1]@ %[contains]@ %@" = "%[Field1]@ %[contains]@ %@";
"%[Field2]@ %[contains]@ %@" = "%[Field2]@ %[contains]@ %@";
您可以将值更改为:
"%[Field1]@ %[contains]@ %@" = "%[Abc]@ %[contains]@ %@";
"%[Field2]@ %[contains]@ %@" = "%[Def]@ %[contains]@ %@";
然后,当您创建NSPredicateEditor
时,您需要将formattingStringsFileName
属性设置为"PredicateEditor"
,编辑器将负责其余的工作。
NSDictionary
这将遵循与.strings选项相同的基本概念,除了您基本上会这样做:
NSDictionary *formatting = @{
@"%[Field1]@ %[contains]@ %@" : @"%[Abc]@ %[contains]@ %@",
@"%[Field2]@ %[contains]@ %@" : @"%[Def]@ %[contains]@ %@"
}
[myPredicateEditor setFormattingDictionary:formatting];
这就是你所要做的一切。
很久以前我blogged about this,而且有更多您可能会觉得有用的信息。
答案 1 :(得分:1)
基本上你想修改弹出按钮中菜单项的标题。这就是你需要做的。它不应该影响您返回的基础谓词。如果您在界面构建器中创建它,则可以轻松获取模板的菜单项并设置其标题。但是,由于您在代码中执行此操作,因此必须在代码中修复它。
这是你如何做到的。在我的行模板类中,我想更改NSTextFields的宽度。所以在我的行模板类中,我会查找它们并像这样修改它们......
- (void)awakeFromNib {
NSArray* views = [self templateViews];
for (id view in views) {
if ([[view class] isEqual:[NSTextField class]]) {
NSRect tfFrame = [view frame];
tfFrame.size.width = 600;
[view setFrame:tfFrame];
}
}
}
您可以看到我获取了templateViews并查找NSTextFields ...然后修改它们。你可以做类似的事情寻找NSPopupButtons。一旦你找到一个检查他们的菜单项标题并寻找标题为“abc”和“def”的标题,并分别将其标题更改为“Field1”和“Field2”。
答案 2 :(得分:0)
不是将NSLocalizedString
与特定格式的选项文字和genstrings
一起使用来生成本地化字符串,而是自己生成最终本地化.strings文件字符串似乎更容易/更清晰。
From this blog post,我们可以使用私有API _generateFormattingDictionaryStringsFile
从NSPredicateEditor本身获取格式化字符串:
extension NSPredicateEditor {
func formattingDictionaryStrings() -> String? {
var strings: String? = nil
if let formattingDictionaryData = self.perform(Selector("_generateFormattingDictionaryStringsFile"))?.takeRetainedValue() as? Data {
strings = String(data: formattingDictionaryData, encoding: .utf16)
}
return strings
}
}
这会生成所有排列,而不需要genstrings
。然后使用用户显示的字符串替换=
右侧的标记。
"%[ABC]@ %[is]@ %[123]@" = "%1$[ABC]@ %2$[is]@ %3$[123]@";
"%[ABC]@ %[is]@ %[456]@" = "%1$[ABC]@ %2$[is]@ %3$[456]@";
"%[ABC]@ %[is]@ %[789]@" = "%1$[ABC]@ %2$[is]@ %3$[789]@";
"%[ABC]@ %[contains]@ %[123]@" = "%1$[ABC]@ %2$[contains]@ %3$[123]@";
"%[ABC]@ %[contains]@ %[456]@" = "%1$[ABC]@ %2$[contains]@ %3$[456]@";
"%[ABC]@ %[contains]@ %[789]@" = "%1$[ABC]@ %2$[contains]@ %3$[789]@";
更好的是,您可以构建构建每个NSPredicateEditorRowTemplate
的代码,以将谓词内部使用的密钥路径和该选项的本地化字符串作为输入。
然后,您的方法可以生成上面的字符串,但已经插入了正确的本地化。
注意:调用此_generateFormattingDictionaryStringsFile
私有API方法似乎会导致NSPredicateEditor中的随机崩溃:
此类不是键
rowType
符合键值编码。
因此,请确保在需要时运行一次,但在您正常运行或测试应用时,请不要将其保持活动状态。
答案 3 :(得分:0)
是的,这完全取决于本地化,这要归因于对象是菜单项。而且它们可以很容易地被对待。
您需要做的只是...
以下是直接在.strings文件中更改内容的示例: 将 is 更改为 ist ,将 booktitle 更改为 Buchtitel
/* Class = "NSMenuItem"; title = "is"; ObjectID = "G1c-st-GEK"; */
"G1c-st-GEK.title" = "ist";
/* Class = "NSMenuItem"; title = "booktitle"; ObjectID = "nQh-54-5Nx"; */
"nQh-54-5Nx.title" = "Buchtitel";
备注:查找要更改的行的最佳方法是查找 ObjectID 。 UIB身份检查器可以为每个MenuItem找到它: