1

我发现某些 NSPredicateEditor/NSPredicateEditorRowTemplate值正在由 OS X 自动本地化。

.equalTo这在 operator:到 string的映射中很容易观察到is

但我刚刚注意到 UTI 字符串被映射到该 UTI 的人类可读版本。

下面,我设置"public.image"但它随后显示为"image".

NSPredicateEditor 中的 UTI 运算符

func setupPredicateEditor() {
    let left = [NSExpression(forKeyPath: "Type")]

    let operators = [NSComparisonPredicate.Operator.equalTo.rawValue as NSNumber]

    let right = [
        NSExpression(forConstantValue: "public.image"),
        NSExpression(forConstantValue: "public.text"),
        NSExpression(forConstantValue: "public.fakeUTI"),
        ];

    let rowTemplate = NSPredicateEditorRowTemplate.init(leftExpressions: left, rightExpressions: right, modifier: .all, operators: operators, options: 0)
    predicateEditor.rowTemplates = [rowTemplate]

    predicateEditor.addRow(self)
}

只有某些有效的 UTI 以这种方式映射。我不知道是否为运算符和 UTI 之外的其他格式提供了自动本地化字符串。

这是一个问题,因为我想本地化我的 NSPredicateEditor 和 Row Templates

本地化谓词的过程涉及将键与本地化值匹配。

KEY: "%[left]@ %[is]@ %[right]@"
VAL: "%1$[left_display_string]@ %2$[is]@ %3$[right_display_string]@"

问题是键中的值必须与UI 中显示的字符串匹配。不是最初设置为行模板的左右表达式的字符串。

因此,我无法"public.image"在密钥中使用本地化。UI 出于某种原因已经将其本地化为"image". 如果我想本地化行模板,我必须改用字符串"image"。而且我不知道这个"image"字符串是如何或为什么被选中的。

我可以通过测试确定这些字符串,然后编写一个将表达式映射到本地化字符串的表。但我更希望有一个禁用这种自动本地化的解决方案,这样我就不必担心我没有测试过的字符串。

为什么 UTI 会自动本地化?其他值是否接受相同的处理?

有没有办法禁用 UTI 字符串和/或整个谓词编辑器的自动本地化?

4

3 回答 3

1

You can call the private API methods directly to use the system's mapping.

In Swift this requires a bridging header:

#import <AppKit/AppKit.h>

@interface NSPredicateEditorRowTemplate ()

- (NSString *)_displayValueForKeyPath:(CFStringRef)keyPath;
- (NSString *)_displayValueForConstantValue:(CFStringRef)constantValue;
- (NSString *)_displayValueForCompoundPredicateType:(NSCompoundPredicateType)compoundPredicateType;
- (NSString *)_displayValueForPredicateOperator:(NSPredicateOperatorType)predicateOperator;

@end

These private methods can then be called like so:

let keyPath = rowTemplate._displayValue(forKeyPath: kMDItemFSSize) // "File size"
let constantValue = rowTemplate._displayValue(forConstantValue: "com.apple.application" as CFString) // "application"
let compoundPredicateType = rowTemplate._displayValue(for: .or) // "Any"

The three above work, but I'm currently having issues with _displayValueForPredicateOperator: crashing with EXC_BAD_ACCESS or returning the wrong string translation.

于 2019-06-10T07:56:14.443 回答
1

不是答案,而是一些信息:NSPredicateEditorRowTemplate将字符串翻译成_displayValueForConstantValue:. 它使用字典:

{
    "com.apple.application" = application;
    "com.apple.pict" = PICT;
    "com.apple.protected-mpeg-4-audio" = "purchased music";
    "com.apple.rtfd" = RTFD;
    "com.compuserve.gif" = GIF;
    "com.microsoft.bmp" = BMP;
    "public.audio" = music;
    "public.folder" = folder;
    "public.html" = HTML;
    "public.image" = image;
    "public.jpeg" = JPEG;
    "public.jpeg-2000" = "JPEG 2000";
    "public.mp3" = MP3;
    "public.mpeg-4-audio" = "MPEG4 audio";
    "public.png" = PNG;
    "public.rtf" = RTF;
    "public.source-code" = "source code";
    "public.text" = text;
    "public.tiff" = TIFF;
    "public.xml" = XML;
}

BT:

AppKit`-[NSPredicateEditorRowTemplate _displayValueForConstantValue:] + 913
AppKit`-[NSPredicateEditorRowTemplate _viewFromExpressions:] + 589
AppKit`-[NSPredicateEditorRowTemplate initWithLeftExpressions:rightExpressions:modifier:operators:options:] + 205

编辑:

_displayValueForKeyPath:使用这本词典:

{
    kMDItemContentCreationDate = Created;
    kMDItemContentModificationDate = "Last modified";
    kMDItemContentTypeTree = "File type";
    kMDItemDisplayName = "File display name";
    kMDItemFSContentChangeDate = "Change date";
    kMDItemFSCreationDate = "Creation date";
    kMDItemFSName = "File name";
    kMDItemFSOwnerGroupID = "Owner group id";
    kMDItemFSOwnerUserID = "Owner user ID";
    kMDItemFSSize = "File size";
    kMDItemLastUsedDate = "Last opened";
    kMDItemPath = "File path";
}

_displayValueForPredicateOperator:并将_displayValueForCompoundPredicateType:枚举转换为字符串。

这应该记录在案,但事实并非如此。我设置了一个断点,_displayValueForConstantValue:然后观察发生了什么。字典是硬编码的,在其他版本的 macOS 中可能会有所不同。

于 2017-02-07T15:06:48.280 回答
0

扩展 Willeke 的最佳答案:

将符号断点添加到以下私有方法以查看映射。

  • _displayValueForKeyPath:
  • _displayValueForConstantValue:
  • _displayValueForCompoundPredicateType:
  • _displayValueForPredicateOperator:

当你中断时,将断点放在包含的行上objc_msgSend并在那里再次中断。

然后输入po $rax打印映射表。

在较低的两种情况下,它不使用字典,但是当断点被命中时可以看到字符串。

_displayValueForKeyPath:

{
    kMDItemContentCreationDate = Created;
    kMDItemContentModificationDate = "Last modified";
    kMDItemContentTypeTree = "File type";
    kMDItemDisplayName = "File display name";
    kMDItemFSContentChangeDate = "Change date";
    kMDItemFSCreationDate = "Creation date";
    kMDItemFSName = "File name";
    kMDItemFSOwnerGroupID = "Owner group id";
    kMDItemFSOwnerUserID = "Owner user ID";
    kMDItemFSSize = "File size";
    kMDItemLastUsedDate = "Last opened";
    kMDItemPath = "File path";
}

_displayValueForConstantValue:

{
    "com.apple.application" = application;
    "com.apple.pict" = PICT;
    "com.apple.protected-mpeg-4-audio" = "purchased music";
    "com.apple.rtfd" = RTFD;
    "com.compuserve.gif" = GIF;
    "com.microsoft.bmp" = BMP;
    "public.audio" = music;
    "public.folder" = folder;
    "public.html" = HTML;
    "public.image" = image;
    "public.jpeg" = JPEG;
    "public.jpeg-2000" = "JPEG 2000";
    "public.mp3" = MP3;
    "public.mpeg-4-audio" = "MPEG4 audio";
    "public.png" = PNG;
    "public.rtf" = RTF;
    "public.source-code" = "source code";
    "public.text" = text;
    "public.tiff" = TIFF;
    "public.xml" = XML;
}

_displayValueForCompoundPredicateType:

0x7fff32a7342c <+20>: leaq   0x5ca25255(%rip), %rax    ; @"Any"
0x7fff32a73434 <+28>: leaq   0x5c9c8dad(%rip), %rax    ; @"None"
0x7fff32a7343c <+36>: leaq   0x5ca00ac5(%rip), %rax    ; @"All"
0x7fff32a73456 <+62>: leaq   0x5ca2524b(%rip), %rdx    ; @"(unknown compound type %ld)"

_displayValueForPredicateOperator:

0x7fff32a7331b <+42>:  leaq   0x5ca251c6(%rip), %rax    ; @"is less than"
0x7fff32a73332 <+65>:  leaq   0x5ca251cf(%rip), %rax    ; @"is less than or equal to"
0x7fff32a7334a <+89>:  leaq   0x5ca252f7(%rip), %rax    ; @"between"
0x7fff32a73356 <+101>: leaq   0x5ca251cb(%rip), %rax    ; @"is greater than"
0x7fff32a73362 <+113>: leaq   0x5ca251df(%rip), %rax    ; @"is greater than or equal to"
0x7fff32a7336b <+122>: leaq   0x5ca251f6(%rip), %rax    ; @"is"
0x7fff32a73374 <+131>: leaq   0x5ca2520d(%rip), %rax    ; @"is not"
0x7fff32a7337d <+140>: leaq   0x5ca25224(%rip), %rax    ; @"matches"
0x7fff32a73386 <+149>: leaq   0x5ca2523b(%rip), %rax    ; @"is like"
0x7fff32a7338f <+158>: leaq   0x5ca25252(%rip), %rax    ; @"begins with"
0x7fff32a73398 <+167>: leaq   0x5ca25269(%rip), %rax    ; @"ends with"
0x7fff32a733a1 <+176>: leaq   0x5ca01300(%rip), %rax    ; @"in"
0x7fff32a733aa <+185>: leaq   0x5ca25277(%rip), %rax    ; @"contains"
0x7fff32a733d4 <+227>: leaq   0x5ca2528d(%rip), %rdx    ; @"(unknown predicate operator %ld)"
于 2019-06-10T06:50:26.140 回答