6

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

    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"

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

4

4 回答 4

11

是的,你可以这样做。

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

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

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

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

  1. 使用 .strings 文件
  2. 带着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];

这就是你所要做的。

我很久以前在博客上写过这个,其中包含更多您可能会发现有用的信息。

于 2012-12-07T05:12:05.843 回答
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”。

于 2012-12-07T00:45:44.840 回答
0

NSLocalizedString与其使用特定格式的选项文字并生成本地化字符串,不如genstrings自己生成最终的本地化 .strings 文件字符串似乎更容易/更干净。

从这篇博文中,我们可以使用 Private 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 中的随机崩溃:

此类与 key 的键值编码不兼容rowType

因此,请务必在需要时运行一次,但不要在您正常运行或测试应用程序时使其处于活动状态。

于 2017-01-08T05:36:53.983 回答
0

是的,这完全是本地化问题,这要归功于对象是菜单项这一事实。他们可以很容易地被对待。

你需要做的就是...

  • 本地化您的应用程序。
  • 然后输入 .strings 文件并将值更改为您想要显示的值或...使用管理/翻译本地化应用程序的工具。

这是直接在 .strings 文件中更改内容的示例:更改istbooktitleBuchtitel

/* 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 找到此信息:

在此处输入图像描述

于 2018-07-02T20:43:26.430 回答