Сценарии Какао: Возвращение клонированных объектов из "дублированной" команды

AppleScript duplicate Команда должна возвращать скопированные объекты.

И хотя приложения, использующие оригинальные функции на основе АЕ, похоже, делают это, приложения, основанные на платформе сценариев Cocoa, похоже, никогда не возвращают ничего, кроме пропущенного значения.

Похоже, что командный обработчик NSCloneCommand отвечает за не возвращение спецификаторов для клонированных объектов.

Я пытался исправить это в своем скриптовом приложении, создав подклассы команды, собрав спецификаторы клонированных объектов и затем вернув их.

Это хорошо работает, если дублируется только один элемент.

Это также работает, если несколько элементов клонируются вместе с использованием to параметр с командой (как в duplicate every widget to end): Тогда я могу вернуть спецификатор типа NSRangeSpecifier это обозначает первый и последний из этих клонированных предметов.

Тем не менее, если использовать команду дубликата для нескольких элементов без to Параметр, затем элементы сортируются в массив непоследовательным образом. Например, если изначально есть 2 элемента "x" с идентификаторами 1 и 2, duplicate every x вставит копию каждого элемента сразу после оригинала, чтобы они были в следующем порядке: 1, 3, 2, 4.

Теперь, как можно вернуть спецификатор для этого, то есть спецификатор для пунктов 3 и 4?

В подклассах NSScriptObjectSpecifier, и я не могу вернуть NSArray для каждого человека NSScriptObjectSpecifier либо, похоже. И пока NSAppleEventDescriptor поддерживает создание списков, я не могу понять, как я бы преобразовал спецификаторы объекта в NSAppleEventDescriptors.

Как я могу решить эту проблему, кроме навязывания последовательного порядка клонированных объектов (что потребовало бы от меня повторной реализации NSCloneCommand боюсь целиком, боюсь).

Кстати, Mark Alldritt, автор Script Debugger, подтверждает проблему, duplicate (также: move, open) не возвращайте значения, как они должны.

2 ответа

Решение

Mark Alldritt помог мне немного подробнее рассказать о некоторых методах частного API:

@interface NSScriptObjectSpecifier (NSPrivate)
+ (id) _scriptingSpecifierWithDescriptor:(NSAppleEventDescriptor*) descriptor;
+ (id) _objectSpecifierFromDescriptor:(NSAppleEventDescriptor*) descriptor inCommandConstructionContext:(id) context;
- (NSAppleEventDescriptor*) _asDescriptor;
@end

_asDescriptor был то, что я искал - способ превратить спецификатор объекта в NSAppleEventDescriptor так что я могу добавить это к списку объектов. Код для этого будет выглядеть так:

- (NSAppleEventDescriptor*) objectSpecifiersAsList:(NSArray*) objectSpecifiers {
    NSAppleEventDescriptor* result = [NSAppleEventDescriptor listDescriptor];
    for (NSScriptObjectSpecifier* specifier in objectSpecifiersArray) {
        [result insertDescriptor:specifier._asDescriptor atIndex:0];
    }
    return  result;
}

Когда я попытался вернуть непоследовательные элементы, я обнаружил, что это не работает. На самом деле это имеет тот же эффект, что и возврат NSArray того же самого NSScriptObjectSpecifiers. Вот пример:

set x to duplicate widgets 1 thru 2

С обработчиком пользовательских дубликатов команд, возвращающим список спецификаторов для скопированных элементов 3 и 4, AppleScript заканчивает тем, что вызывает тот же обработчик команд второй раз, и после этого он выдает ошибку -10006 с сообщением:

Can't set widgets 1 thru 2 to widgets 1 thru 2

Имейте в виду - это не говорит "виджеты с 3 по 4" или "{виджет 3, виджет 4}". Нет, он всегда сообщает об элементах, которые были заданы в первом параметре, команде дубликата.

Как только я изменяю свой код на возвращение одного спецификатора или спецификатора диапазона, команда снова работает нормально.

Таким образом, кажется, что это скрытая ошибка в сценариях Какао (или AppleScript?), В которой он не может обработать возвращенные спецификаторы объекта в списке.

Обновление и решение

После дополнительных проб и ошибок я выяснил, как это работает:

Тип результата должен быть изменен с "дескриптор", и есть две возможности:

  • Чтобы использовать код выше, который возвращает listDescriptorтип результата должен быть "любым", то есть:

    <result>
        <type type="any"/>
    </result>
    
  • В качестве альтернативы, если тип результата изменяется на "список любого", то можно вернуть NSArray, содержащий NSAppleEventDescriptor ценности:

    <result>
        <type type="any" list="yes"/>
    </result>
    

Оба решения требуют использования частного _asDescriptor метод, однако, так как нет другого известного способа превратить объект сценариев в NSAppleEventDescriptor,

(Конечно, если ваше приложение поддерживает duplicate Команда только для одного типа элемента, затем вы можете изменить тип на "список вашего типа" и просто вернуть NSArray ваших объектов, без необходимости частного метода - это необходимо только для возврата результатов типа any.)

Марк говорит об использовании частного метода:

Если вы обеспокоены проблемами магазина Mac App Store, эти частные методы были предоставлены мне Apple, так как нет альтернативного API. Я уверен, что вы можете получить разрешение на их использование.

Я надеюсь вскоре представить свое собственное приложение, реализующее это решение, в App Store. Затем я дополню этот ответ результатами использования закрытой функции.

Томас, я не уверен, что это была опечатка, но я не вижу параметра "at" для дублирующейся команды в Standard Suite:

<command name="duplicate" code="coreclon" description="Copy an object.">
    <cocoa class="NSCloneCommand"/>
    <direct-parameter type="specifier" .../>
    <parameter name="to" ...</parameter>
    <parameter name="with properties" ...</parameter>
</command>

Там же нет <result ...> элемент, поэтому команда не должна возвращать какое-либо значение или значения по определению. Я что-то пропустил?

Другие вопросы по тегам