use语句在AppleScript中不起作用

时间:2015-05-05 09:16:52

标签: applescript

我正在脚本文件中创建我的第一个AppleScript库,并希望使用use语句(I followed these instructions)在该文件中使用处理程序。所以我试过了:

use script "My Library"

create_new_track(10, 2, 2)

在我的"我的Library.scpt"文件,有一个名为" create_new_track"的处理程序。 但是当我尝试在use语句之后调用它时,我收到了这个错误:

error "«script» doesn’t understand the “create_new_track” message." number -1708 from «script»

使用以下代码段,我得到运行处理程序:

tell script "My Library"
    create_new_track(10, 2, 2)
end tell

但我宁愿能够在我的脚本中避免使用多个tell块。任何人都知道出了什么问题?

3 个答案:

答案 0 :(得分:1)

不幸的是,您假设AppleScript的图书馆系统是由一位称职的工程师设计的。事实并非如此:就像当前AppleScript团队喷出的几乎所有东西一样,它是小丑车的软件版本:完全不可预测,危险不安全,以及你认为你最终弄清楚它是怎么回事的那一刻工作,所有的门都飞了起来,数十个疯狂的小丑跳出来,给你带来难以形容的物质。

无论如何,试着尽力解释疯狂......

use语句将字典定义的关键字注入全局命名空间。考虑到AppleScript因在语言,应用程序和脚本添加词典之间创建术语冲突而臭名昭着,这本身就是一件疯狂的事情。

但是,use语句注入用户定义的标识符(例如您的create_new_track标识符)。这有点讽刺,因为用户定义的标识符混合比任意关键字更安全,并且它会使ObjC框架使用起来更加烦人(我的意思是,地球上有什么让他们认为current application's NSWhatever...是良好的语法?!?!!)。

虽然AppleScript确实在正确绑定静态变量名时遇到问题,但处理程序名称始终是动态绑定的,因此用户定义的命令名通常可以正常工作(消息只是传递给对象委托链直到它被处理或者& #34;找不到处理程序"发生错误)。但是,use机制并没有使用标准的AppleScript委派(并不是用于此类用途),而是依赖于已知关键字的全局查找表来拦截带有关键字的消息基于名称并将这些消息重定向到最初定义该关键字的任何对象。但是,由于您的create_new_track邮件没有基于关键字的名称,因此该"重定向"黑客完全无视它; AppleScript种族隔离,如果你愿意的话。

因此,如果要引用脚本库中具有用户定义名称的属性和处理程序,则必须使用引用,例如create_new_track() of script "MyLibrary"。这实际上是一件好事,并将整个混乱带到了简单,可预测和安全的地方。因为它留下了所有的脚本'命名空间完好无损,并且不会将任何可能存在冲突的关键字注入AppleScript的全局命名空间。

如果您反复使用某个库,那么编写...of script "MyLibrary"确实会变得乏味。虽然您可以使用tell script "MyLibrary"...end tell块来包装多个命令,但过度使用tell块是另一种简单的方法来创建完全混淆,因为它们指定了所有命令的默认目标块,而不仅仅是您实际想要发送到该对象的块。最好的解决方案是在脚本顶部使用property语句将script...说明符绑定到一个漂亮,整洁的标识符,然后您可以在需要时使用整个脚本的其余部分。向该库发送命令:

property mylib : script "My Library"

...

mylib's do_this()

mylib's do_that()

etc.

使用这种方法,你可以避免大量的痛苦。尽量做到聪明,并且它几乎总是咬你的屁股。掌握AppleScript语言一直都是学习它的许多缺陷以及如何在实际学习编码时解决它们。令人遗憾的是,目前的AS团队如此专注于放纵自己的病态聪明,以至于年复一年变得更难,而不是更容易。 (我希望AS最终能够超越C ++,假设其余的苹果公司并不是首先放入一个子弹 - 作为一个15年的AS老手,我越来越希望他们在扼杀用户脚本和自动化之前做到这一点完全。)

答案 1 :(得分:1)

指出一些有用的信息…如果您选择使用属性定义脚本库的方法,以便能够调用要在其他脚本中使用的处理程序和脚本对象,那么请务必记住,如果有的话对脚本库文件进行的更改…并重新编译并保存,这些更改将不会延续到您创建的脚本中,这些脚本从您的库文件中调用脚本对象和处理程序。简而言之,您将需要打开,重新编译并保存创建的每个脚本,这些脚本会从库文件中调用脚本对象和处理程序。如果您有数十个甚至数百个脚本,这可能成为噩梦。

从另一个答案中使用下面的示例……脚本库在编译时存储,并将保留其值,直到重新编译脚本为止。对原始库文件的任何更新或更改都不会反映在调用它们的脚本中,直到这些脚本也被重新编译并保存

property mylib : script "My Library"

...

mylib's do_this()

mylib's do_that()

etc.

我认为一个更有利的选择是在运行时加载脚本库。这样,依赖于该库文件的任何脚本都将在运行时自动更新……在更改并保存了脚本库文件之后。

这是我用于在运行时加载库的代码

property myLib : missing value
property theLibrary : missing value

on loadLibraries()
    set theLibrary to (path to home folder as text) & "Library:Script Libraries:My Library.scpt"
    set myLib to load script alias theLibrary
end loadLibraries

loadLibraries()

myLib's do_this()
myLib's do_that()

答案 2 :(得分:0)

我想我会尝试:

 use mylib : script "My Library"
 mylib's create_new_track(10, 2, 2)

如果我说得对,你只能像上面那样使用use语句,以便使用app中的术语。 - 但我可能错了。