NSPredicateEditor& NSExpression - 显示是否可以与谓词的值不同?

时间:2012-12-06 18:02:26

标签: objective-c cocoa nspredicate nspredicateeditor nsexpression

我有一个谓词编辑器,模板是通过以下方式生成的:

    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)];

所以如果我填写这样的谓词编辑器: Predicate Editor

当我退出生成的谓词时,我得到:

Abc CONTAINS[cd] "abc" OR Def CONTAINS[cd] "def"

我想知道的是,如果我能以某种方式让谓词编辑器模板显示与生成的谓词中设置的值不同。

EX:我希望输出谓词具有:

Field1 CONTAINS[cd] "abc" OR Field2 CONTAINS[cd] "def"

即使编辑器仍然显示abcdef作为字段。这可能吗?

4 个答案:

答案 0 :(得分:10)

是的,你可以这样做。

您希望左表达式数组是最终谓词中的实际keyPath。在您的情况下,"Field1""Field2"

至于在弹出窗口中显示不同的值,这里有一个令人费解的概念:

您要将谓词编辑器本地化为英语

有两种方法可以做到这一点。

  1. 使用.strings文件
  2. 使用NSDictionary
  3. 使用.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文件并将其值更改为要显示的值 要么... 使用工具来管理/翻译本地化的应用。

以下是直接在.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找到它:

enter image description here