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)];
Так что, если я заполню редактор предикатов следующим образом:
Когда я выхожу из сгенерированного предиката, я получаю:
Abc CONTAINS[cd] "abc" OR Def CONTAINS[cd] "def"
Что мне интересно, так это то, что я могу каким-то образом показать, как шаблон редактора предикатов будет отличаться от значения, установленного в сгенерированном предикате.
EX: я хочу, чтобы выходной предикат имел:
Field1 CONTAINS[cd] "abc" OR Field2 CONTAINS[cd] "def"
Даже если редактор все еще отображает abc
а также def
как поля. Это возможно?
4 ответа
Да, ты можешь это сделать.
Вы хотите, чтобы массив левых выражений был фактическим keyPaths в конечном предикате. В твоем случае, "Field1"
а также "Field2"
,
Что касается того, чтобы во всплывающем окне появлялось другое значение, то здесь возникает умопомрачительная концепция:
Вы собираетесь локализовать свой редактор предикатов на английский.
Есть два способа сделать это.
- С файлом.strings
- С
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];
Это все, что вам нужно сделать.
Я писал об этом давным-давно, и там есть больше информации, которая может оказаться полезной.
В основном вы хотите изменить заголовок пунктов меню в вашей всплывающей кнопке. Это все, что вам нужно сделать. Это не должно влиять на основной предикат, который вы получите. Если вы создали его в конструкторе интерфейсов, легко получить доступ к пунктам меню шаблона и установить их заголовок. Но так как вы сделали это в коде, вам придется исправить это в коде.
Вот как вы можете это сделать. В моем классе шаблона строки я хотел изменить ширину моих полей 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" соответственно.
Да, все дело в локализации, благодаря тому, что объекты являются пунктами меню. И к ним так легко относиться.
Все, что вам нужно сделать, это...
- локализуйте ваше приложение.
- Затем введите файл.strings и измените значение на то, что вы хотите отображать, или... используйте инструменты для управления / перевода локализованных приложений.
Вот пример изменения вещей непосредственно в файле.strings: Изменение заключается в том, чтобы 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. Это может быть найдено для каждого MenuItem инспектором идентификации UIB:
Вместо того, чтобы использовать 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:
этот класс не соответствует значению ключа для ключа
rowType
,
Поэтому обязательно запускайте его один раз, когда это необходимо, но не оставляйте его активным, когда вы обычно запускаете или тестируете свое приложение.