Cocoa Scripting:从“重复"对象中返回克隆对象命令 [英] Cocoa Scripting: Returning the cloned objects from a "duplicate" command

查看:16
本文介绍了Cocoa Scripting:从“重复"对象中返回克隆对象命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

AppleScript duplicate 命令应该返回复制的对象.

The AppleScript duplicate command is supposed to return the copied objects.

虽然使用原始基于 AE 的函数的应用程序似乎可以做到这一点,但基于 Cocoa Scripting 框架的应用程序似乎从不返回任何东西,只是缺失值.

And while apps using the original AE-based functions seem to do that, apps based on the Cocoa Scripting framework seem to never return anything but missing value.

看来 NSCloneCommand 的命令处理程序负责不返回克隆对象的说明符.

It appears that the command handler of NSCloneCommand is responsible for not returning the specifiers for the cloned objects.

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

I was attempting to fix this in my scriptable app by subclassing the command, collecting the cloned object specifiers and then returning them.

如果只有一项重复,这很有效.

This works well if only one item is duplicated.

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

It also works if multiple items are cloned along with using the to parameter with the command (as in duplicate every widget to end): Then I can return a specifier of type NSRangeSpecifier that designates the first and last of those cloned items.

但是,如果在多个项目上使用重复命令to 参数,那么这些项目将被排序到数组中非连续方式.例如,如果最初有 2 个x"元素,id 为 1 和 2,duplicate every x 将在每个元素的原始元素之后插入一个副本,以便我们将它们放在这个顺序:1、3、2、4.

However, if one uses the duplicate command on multiple items without the to parameter, then the items get sorted into the array in a non-consecutive manner. For instance, if there are initially 2 "x" elements, with id 1 and 2, duplicate every x will insert a copy of each element right after its original, so that we'll have them in this order: 1, 3, 2, 4.

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

NSScriptObjectSpecifier 的子类中没有列表"说明符,而且我似乎也无法为每个单独的 NSScriptObjectSpecifier 返回 NSArray.虽然 NSAppleEventDescriptor 支持创建列表,但我不知道如何将对象说明符转换为 NSAppleEventDescriptors.

There is no "list" specifier in the sub classes of NSScriptObjectSpecifier, and I cannot return an NSArray for each individual NSScriptObjectSpecifier either, it seems. And while NSAppleEventDescriptor supports creation of lists, I cannot figure out how I'd convert the object specifiers into NSAppleEventDescriptors.

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

How can I solve this other than enforcing a consecutive order of the cloned objects (which would require me to re-implement the NSCloneCommand's operation entirely, I'm afraid).

顺便说一句,Mark Aldritt,脚本调试器的作者,确认问题重复(还有:moveopen) 不返回应有的值.

BTW, Mark Aldritt, author of Script Debugger, confirms the issue that duplicate (also: move, open) do not return values as they're supposed to.

推荐答案

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

Mark Aldritt helped me a little further, telling me about some private API methods:

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

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

The _asDescriptor was what I was looking for - a way to turn an object specifier into a NSAppleEventDescriptor so that I can add that to a list object. The code for that would look like this:

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

当我尝试返回非连续项目时,我发现这不起作用.实际上,它与返回相同 NSScriptObjectSpecifierNSArray 具有相同的效果.举个例子:

When I tried this to return the non-consecutive items, I found, however, that this doesn't work. In fact, it has the same effect as returning an NSArray of the same NSScriptObjectSpecifiers. Here's an example:

set x to duplicate widgets 1 thru 2

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

With the custom duplicate command handler returning a list of specifiers for the copied items 3 and 4, AppleScript ends up calling the same command handler a second time and after that it gives the error -10006 with the message:

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

请注意 - 它不会说小部件 3 到 4"或{小部件 3,小部件 4}".不,它总是将第一个参数中给出的项目报告给重复命令.

Mind you - it does not say "widgets 3 thru 4" or "{widget 3, widget 4}". No, it always reports the items that were given at the first parameter to the duplicate command.

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

As soon as I change my code to returning a single specifiers or a range specifier, the command behaves normally again.

所以这似乎是 Cocoa Scripting(或 AppleScript?)中的一个隐藏错误,它无法处理列表中返回的对象说明符.

So it seems like this is a hidden bug in Cocoa Scripting (or AppleScript?) wherein it cannot handle returned object specifiers in a list.

更新&解决方案

经过多次反复试验,我找到了一种有效的方法:

After more trial-and-error I figured out a way that works:

结果的类型必须从描述符"改变,有两种可能:

The type for the result has to be changed from "descriptor", and there are two possibilities:

  • 要使用上面返回listDescriptor的代码,结果类型需要是any",即:

  • To use the code above that returns a listDescriptor, the result type needs to be "any", i.e.:

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

  • 或者,如果结果类型更改为list of any",则可以返回一个包含 NSAppleEventDescriptor 值的 NSArray:

  • Alternatively, if the result type is changed to "list of any", then one can return an NSArray containing the NSAppleEventDescriptor values:

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

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

    Both solutions require the use of the private _asDescriptor method, however, as there is no other known way to turn a scriptable object into a NSAppleEventDescriptor.

    (当然,如果您的应用程序仅支持一种类型的元素的 duplicate 命令,那么您可以将类型更改为list of yourtype"并简单地返回对象的 NSArray,而无需需要私有方法 - 只需要返回 any 类型的结果.)

    (Of course, if your app supports the duplicate command for only one type of element, then you can change the type to "list of yourtype" and return simply an NSArray of your objects, without the need for the private method - that's only needed for returning results of type any.)

    Mark 说到使用私有方法:

    Mark says this about using the private method:

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

    If you are concerned about Mac App store issues, these private methods were give to me by Apple as there is no alternative API. I’m pretty sure you can get permission to use them.

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

    I hope to submit my own app implementing this solution to the App Store soon. I shall then update this answer with the outcome of using the private function.

    这篇关于Cocoa Scripting:从“重复"对象中返回克隆对象命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆