1

AppleScriptduplicate命令应该返回复制的对象。

虽然使用原始 AE 函数的应用程序似乎可以做到这一点,但基于 Cocoa 脚本框架的应用程序似乎永远不会返回除了缺失值之外的任何内容。

似乎命令处理程序NSCloneCommand负责不返回克隆对象的说明符。

我试图通过子类化命令、收集克隆的对象说明符然后返回它们来在我的脚本化应用程序中解决这个问题。

如果只有一个项目被复制,这很有效。

如果多个项目与命令一起使用to参数被克隆(如duplicate every widget to end),它也可以工作:然后我可以返回一个类型的说明符NSRangeSpecifier,指定这些克隆项目中的第一个和最后一个。

但是,如果在没有to参数的情况下对多个项目使用重复命令,则项目将以非连续方式排序到数组中。例如,如果最初有 2 个 "x" 元素,id 为 1 和 2,duplicate every x将在每个元素的原始元素之后插入每个元素的副本,因此我们将按以下顺序拥有它们:1、3、2、4。

现在,如何为此返回一个说明符,即第 3 项和第 4 项的说明符?

的子类中没有“列表”说明符,而且我似乎NSScriptObjectSpecifier也不能为每个人返回一个 NSArray 。NSScriptObjectSpecifier虽然NSAppleEventDescriptor支持创建列表,但我无法弄清楚如何将对象说明符转换为 NSAppleEventDescriptors。

除了强制克隆对象的连续顺序之外,我该如何解决这个问题(恐怕这需要我完全重新实现NSCloneCommand's 操作)。

顺便说一句,Script Debugger 的作者Mark Aldritt确认了( duplicatealso: move, open) 没有按预期返回值的问题。

4

2 回答 2

1

Mark Aldritt进一步帮助了我,告诉我一些私有 API 方法:

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

_asDescriptor是我一直在寻找的 - 一种将对象说明符转换为 a 的方法,NSAppleEventDescriptor以便我可以将其添加到列表对象中。代码如下所示:

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

但是,当我尝试使用此方法返回非连续项目时,我发现这不起作用。实际上,它与返回NSArray相同NSScriptObjectSpecifiers的an具有相同的效果。这是一个例子:

set x to duplicate widgets 1 thru 2

使用自定义重复命令处理程序返回复制项 3 和 4 的说明符列表,AppleScript 最终会第二次调用相同的命令处理程序,然后它给出错误 -10006 并显示以下消息:

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

请注意 - 它没有说“widgets 3 thru 4”或“{widget 3, widget 4}”。不,它总是将第一个参数中给出的项目报告给重复命令。

一旦我将代码更改为返回单个说明符或范围说明符,该命令就会再次正常运行。

因此,这似乎是 Cocoa 脚本(或 AppleScript?)中的一个隐藏错误,它无法处理列表中返回的对象说明符。

更新与解决方案

经过更多的反复试验,我找到了一种可行的方法:

结果的类型必须从“描述符”更改,有两种可能:

  • 要使用上面返回 a 的代码listDescriptor,结果类型必须是“any”,即:

    <result>
        <type type="any"/>
    </result>
    
  • 或者,如果结果类型更改为“任何列表”,则可以返回包含NSAppleEventDescriptor值的 NSArray:

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

然而,这两种解决方案都需要使用私有_asDescriptor方法,因为没有其他已知方法可以将可编写脚本的对象转换为NSAppleEventDescriptor.

(当然,如果您的应用程序duplicate仅支持一种元素类型的命令,那么您可以将类型更改为“您的类型列表”并仅返回对象的 NSArray,而不需要私有方法 - 只需要返回类型的结果any。)

马克说这个关于使用私有方法:

如果您担心 Mac App Store 问题,这些私有方法是 Apple 提供给我的,因为没有替代 API。我很确定您可以获得使用它们的许可。

我希望尽快将实现此解决方案的自己的应用程序提交到 App Store。然后,我将使用私有函数的结果更新这个答案。

于 2016-05-16T10:19:31.517 回答
0

托马斯,我不确定这是否是一个错字,但我没有看到标准套件中重复命令的“at”参数:

<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 ...>元素,因此根据定义,该命令不应返回任何值或值。我错过了什么吗?

于 2016-05-15T20:36:02.833 回答