马克·奥尔德里特进一步帮助了我,告诉我一些私有 API 方法:
@interface NSScriptObjectSpecifier (NSPrivate)
+ (id) _scriptingSpecifierWithDescriptor:(NSAppleEventDescriptor*) descriptor;
+ (id) _objectSpecifierFromDescriptor:(NSAppleEventDescriptor*) descriptor inCommandConstructionContext:(id) context;
- (NSAppleEventDescriptor*) _asDescriptor;
@end
The _asDescriptor
就是我一直在寻找的 - 一种将对象说明符变成NSAppleEventDescriptor
这样我就可以将其添加到列表对象中。其代码如下所示:
- (NSAppleEventDescriptor*) objectSpecifiersAsList:(NSArray*) objectSpecifiers {
NSAppleEventDescriptor* result = [NSAppleEventDescriptor listDescriptor];
for (NSScriptObjectSpecifier* specifier in objectSpecifiersArray) {
[result insertDescriptor:specifier._asDescriptor atIndex:0];
}
return result;
}
然而,当我尝试返回不连续的项目时,我发现这不起作用。其实和返回一个效果是一样的NSArray
一样的NSScriptObjectSpecifier
s。这是一个例子:
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 Scripting(或 AppleScript?)中的一个隐藏错误,其中它无法处理列表中返回的对象说明符。
更新及解决方案
经过多次尝试和错误,我找到了一种有效的方法:
结果的类型必须从“描述符”更改,有两种可能性:
-
使用上面返回的代码listDescriptor
,结果类型需要是“any”,即:
<result>
<type type="any"/>
</result>
-
或者,如果结果类型更改为“任意列表”,则可以返回一个包含以下内容的 NSArrayNSAppleEventDescriptor
values:
<result>
<type type="any" list="yes"/>
</result>
两种解决方案都需要使用私有_asDescriptor
然而,因为没有其他已知的方法可以将可编写脚本的对象转换为NSAppleEventDescriptor
.
(当然,如果你的应用程序支持duplicate
命令仅适用于一种类型的元素,那么您可以将类型更改为“list of yourtype”并仅返回对象的 NSArray,而不需要私有方法 - 仅在返回 type 的结果时才需要any
.)
马克对于使用私有方法是这样说的:
如果您担心 Mac 应用商店问题,这些私有方法是 Apple 给我的,因为没有替代 API。我很确定您可以获得使用它们的许可。
我希望尽快将实现此解决方案的我自己的应用程序提交到 App Store。然后我将用使用私有函数的结果更新这个答案。