Mac Carbon 应用程序中的脚本化 (AppleScript)

Scriptability (AppleScript) in a Mac Carbon application

我正在尝试为我的非 Cocoa 应用程序添加 AppleScripting 支持。

我正在处理 AEGetParamDesc 等低级函数,自己处理 form / want / seld 参数。

我的词汇表提供了一个class,姑且称之为"Image"。它有一个 属性 "name".

我已经获得了一些 Applescript 代码,例如:

get Images
get name of every Image
get count Images
get every Image
get first Image
get Image 1

因此,基本上,对对象及其属性的访问都有效。

然而,当我尝试这些类似的访问表单时,它们都失败了:

get Images whose name = "foo"

repeat with img in Images
end repeat

在第一种情况下,我似乎必须处理 test 表格。

在第二种情况下,计数运算符 (cnte) 不直接请求 class 对象,而是使用描述索引对象的 cobj 运算符。

这一切让我想知道这会走多远。我是否必须在我的代码中单独实现 Applescript 的所有可能语法和运算符?我假设 "whose" 运算符将简单地组合 "every Image" 和 "name of Image x" 的请求,就像我可以在 Applescript 中单独编写它们一样,而不是为每个请求使用不同的 AppleEvent 公式。

whose <boolean-test> 相同。为什么 AppleScript 不简单地执行 name = "foo" 本身的相等性测试,因为它是一个文本比较,根本不应该涉及我的应用程序代码?

有什么我想念的吗?我可以将这些转发到我还不知道的 AE 功能,还是我必须自己处理所有可能的比较和流控制命令?

A​​pple 事件对象模型专为 OS(系统 7)上的高延迟 IPC 而设计,每秒最多可以进行 60 次上下文切换。可以对多个对象进行操作的复杂查询和过程允许使用更少的跨进程消息来完成更多的工作。此外,它被设计成一个相对厚实的 View-Controller 抽象,强调 UI/UX,将用户数据的理想化视图呈现为关系图,而不管底层数据实际如何存储或有多复杂或难以实施 VC 代码以从一个映射到另一个可能是。 AEOM 与关系数据库的共同点远多于 OOP 世界中的任何事物,而与 Apple 事件 IPC 最接近的类比是通过 XML-RPC 发送 XQueries。背景见:

http://www.cs.utexas.edu/~wcook/Drafts/2006/ashopl.pdf

现在,当然,OS X 可以每秒执行数千次进程切换而不费吹灰之力,因此实现复杂的 AE View-Controller 以获得可接受的性能的必要性降低了。 TBH,我建议您节省自己的时间并实施最简单、可靠且快速的最简单的 RPC。将改变状态的处理程序限制为在每条消息上对单个对象进行操作(因为对数组进行 Set 操作很难做到正确),实现定位对象所需的最简单的查询形式,以及 return 基本上起作用的 ID 说明符作为指向先前识别的对象的安全指针,因此用户可以使用进一步的命令快速操作它们,而无需重复往返复杂的完整查询的成本。

哦,除非您有特殊原因要使用 C,否则我建议仅使用 NSAppleEventDescriptor 和 NSAppleEventManager。 C Apple Event Manager API 自 10.6 以来是古老的、粗糙的和遗留的,因此不推荐用于新开发。您可能(重复,可能)甚至找到一种方法来使用一些 Cocoa 脚本 类 来完成一些繁重的工作 w.r.t。对象说明符,虽然 CS 本身非常糟糕并且与 ApplicationKit 紧密耦合,所以不要浪费时间弄乱它,除非它确实有帮助(CS 之前埋没了更好的项目)。

当然,另一件事是整个 Mac 自动化生态系统处于完全垂死的状态,在当前的管理下不太可能好转,因此开发的成本与收益从头开始的完整、复杂的 AEOM 已经不复存在了。如果 "simple, fast, safe, and dumb" 是 "good enough" 对于您希望吸引的任何用户,那就去做吧。

Apple 的 sample code for Sketch 提供了使用 Cocoa 脚本 API.

的一个很好的例子

示例代码不会对 "repeat" 和 "whose" 执行任何特殊处理,但它可以 运行 AppleScripts 使用这些术语。

这表明 Cocoa 脚本,即主要是 NSScriptObjectSpecifiers.h 中的 类 和协议,负责处理旧 Carbon API 公开的复杂处理。

因此,同样基于@foo 的回答,尝试基于 NSObject(NSScriptObjectSpecifiers) 创建代理 类,实施 objectSpecifier 方法以及 get/set 任何属性的访问器,然后使用在 .sdef 文件中引用那些 类 的能力。即使没有 Objective C,这样的 类 也可以使用 ObjC 运行time 函数创建,例如 objc_registerClassPair.

Thomas Tempelmann(因查找任何文件而出名?),如果您真的无法在 Cocoa 中重写应用程序,这里是我多年前写的一篇文章,其中详细介绍了编码(用 C 语言) Cocoa 之前的脚本能力,包括处理 formWhose,您在上面询问过。

http://www.mactech.com/articles/develop/issue_28/reuter.html

这篇文章由 Apple 在其 Develop 杂志上发表,其中包括我为名为 "Sketch" 的示例应用程序编写的源代码。这是在 Apple 发布自己的示例项目之前的几年,该项目也名为 "Sketch." 如果对您有帮助,我仍然有源代码。

祝你好运!