【问题标题】:How to perform equivalent of AppleScript "copy" command from Scripting Bridge?如何从 Scripting Bridge 执行等效的 AppleScript“复制”命令?
【发布时间】:2023-10-02 16:57:02
【问题描述】:

有没有办法从 Scripting Bridge 在容器内进行远程复制?在 AppleScript 中,这看起来像“将 [容器] 的 [元素] 复制到 [容器中的位置]”。例如,在一个文本编辑文档的上下文中,您可以“将其文本的第一段复制到其文本的末尾”以将第一段复制到文档的末尾,同时保留所有格式。

有什么办法可以从 Objective-C 中使用 Scripting Bridge 吗?

我尝试过这样的事情:

SBObject* foo = [container objectAtIndex: 0];
[container addObject: foo];

并收到一条消息“无法添加已存在的对象”。在控制台上;看来addObject 和各种replace* 方法仅在您构建新的SBObject 实例并插入它时才有效。

【问题讨论】:

    标签: objective-c applescript scripting-bridge


    【解决方案1】:

    当 AppleScript 的内置 copy 命令的第二个参数是应用程序引用时,AppleScript 将“有用地”别名为应用程序 duplicateset 命令,具体取决于第一个参数是否是另一个引用。为避免混淆,在 AppleScript 中处理可编写脚本的应用程序时,最好明确使用 duplicateset

    对于 SB,您需要在头文件中查找 duplicate... 方法。请注意,SB 的 duplicate 命令是半瘫痪的 (SB has quite a few shortcomings),因为它一次只能处理一个对象。大多数应用程序将允许您在单个命令中操作多个对象(警告其脚本支持中的任何错误),例如AppleScript 会让你说:

    tell application "iTunes"
        duplicate (every track whose artist is "Foo") to (playlist "Bar")
    end tell
    

    但 SB 不会;相反,您必须提取单个引用列表并对其进行迭代,一次处理一个。使您的代码相当冗长,如果您在其他地方有大量对象,则效率可能非常低。

    另一个选项是objc-appscript,它可以正确完成所有这些工作,并且通常不太容易出现应用程序兼容性问题(正如 Matt Neuburg 所说,“quirk-for-quirk 兼容性”)。此外,您还获得了 ASTranslate,它将 AppleScript 命令转换为等效的 Python/Ruby/ObjC 语法 - 在弄清楚如何正确表达命令时非常方便:

    #import "ITGlue/ITGlue.h"
    ITApplication *itunes = [ITApplication applicationWithName: @"iTunes"];
    ITReference *ref = [[itunes tracks] byTest: [[ITIts artist] equals: @"Foo"]];
    ITDuplicateCommand *cmd = [[ref duplicate] to: [[itunes playlists] byName: @"Bar"]];
    id result = [cmd send];
    

    如果您使用的是 10.6,则另一个选择是使用 AppleScriptObjC 桥接器,它允许您将 AS 和 ObjC 组合在同一个程序中,而不会出现任何讨厌的 NSAppleScript 废话。这将允许您将 AppleScript 用于其最擅长的事情(与其他应用程序通信),并将 ObjC 用于其他所有事情。官方文档is limited,但是网络搜索应该会抛出各种第三方资源。 MacScripter.net 可能是一个不错的起点 - 除了 ASOC 论坛之外,Craig Williams 不久前还发布了一系列教程。

    (顺便说一句,Craig 还为我与人合写的 Apress 的 Learn AppleScript 第三版贡献了一个关于 ASOC 的章节,其中包含有关应用程序脚本编写原则和实践的大量信息,包括对 set/@987654334 的澄清@/copy.)

    【讨论】:

    • 感谢您的彻底治疗!我目前正在混合使用 Scripting Bridge 和 ASOC,看起来我可以勉强应付。
    • 我找到了一个- duplicateTo:(SBObject*) withProperties:(NSDictionary*) 方法,但是如何构建一个SBObject* 指定“[容器] 的结尾”或一些不包含实际对象的类似间隙位置?
    • 你知道,我真的不知道。 SB 开发人员完全有可能忘记添加一种方法来做到这一点,但如果没有进一步的研究,很难确定,因为文档很糟糕,API 混乱且不透明。 (SB 是我写 objc-appscript 的原因,顺便说一句。)您是否尝试过传递对容器本身的引用,但它可能会起作用? (无论如何,有些应用程序需要容器引用。)如果失败,我建议发布到 applescript-implementors 并尝试引起 AS 工程师的注意。或者使用 appscript,基本上 Just Works。
    • 好吧,我已经编写了一个 AppleScriptObjC 类,基本上只是为了运行这个副本(尽管它在对象模型中提供了一个像样的家)。下次我需要对 Apple Events 的精彩世界做任何事情时,我肯定会直接使用 appscript。
    • 您是如何编写 AppleScriptObjC 类的?我花了 2 天时间试图弄清楚如何将现有曲目添加到播放列表。我想我需要在这里做同样的事情只是为了获得 iTunesTrack 的副本
    最近更新 更多