可编写脚本的应用程序示例

Vol*_*ike 3 macos cocoa applescript objective-c scriptable

显然,有一种方法可以让我的 GUI 应用程序可以使用 AppleScript 编写脚本。例如,我可以有一个命令行应用程序(例如从 LaunchDaemon 运行)来告诉我的 GUI 应用程序发布侧边栏通知。有人有一个简单的例子来解释这一点吗?我在苹果网站上看到的一切都很难理解。

我想创建一条 AppleScript 消息,例如:

tell "My App" to notify with title "Title" subtitle "subtitle" text "some text"
Run Code Online (Sandbox Code Playgroud)

在我的 CLI 应用程序中,然后我的 GUI 应用程序唤醒、接收并处理它。

Vol*_*ike 10

这比我想象的要容易!需要注意的一些事项:

\n
    \n
  • 您必须使您的 Cocoa 应用程序能够接收带有 Info.plist 文件中两个特殊参数的 AppleScript 事件:NSAppleScriptEnabledOSAScriptingDefinition
  • \n
  • 一个称为 sdef 文件的特殊 XML 文件将您的 AppleScript 语法直接映射到 Objective C 类来处理它。
  • \n
  • 该类必须NSScriptCommand是其方法的子类performDefaultImplementation,然后您可以访问其中的[self directParameter][self evaluatedArguments]
  • \n
  • 因此,当您发送 AppleScript 命令时,您的应用程序会自动打开(即使关闭),并且不会加载它的多个实例,这很好。然后,如果 AppleScript 中的语法正确,则会将其发送到该类进行处理。sdef 文件指示哪个类。
  • \n
  • 如果您想要的话,您的命令还可以发回响应。或者它可以选择不这样做。
  • \n
\n

1. 打开您想要接收 AppleScript 事件的 OSX Cocoa 应用程序项目。

\n

2. 添加包含以下内容的commands.sdef 文件:

\n
<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">\n<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">\n    <!-- commented out next line because it has a bug ".sdef warning for argument \'FileType\' of command \'save\' in suite \'Standard Suite\': \'saveable file format\' is not a valid type name" -->\n    <!-- <xi:include href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite)"/> -->\n    <suite name="Acceptable Commands" code="SVrb" description="">\n        <command name="notify user with title" code="SVrbDpCm" description="">\n            <cocoa class="myCommand"/>\n            <direct-parameter description="">\n                <type type="text"/>\n            </direct-parameter>\n            <parameter name="subtitle" code="arg2" type="text" optional="yes"\n                    description="">\n                    <cocoa key="subtitle"/>\n            </parameter>\n            <parameter name="text" code="arg3" type="text" optional="yes"\n                    description="">\n                    <cocoa key="text"/>\n            </parameter>\n            <!-- uncomment below if you want to return a result string -->\n            <!-- <result type="text" description=""/> -->\n        </command>\n    </suite>\n</dictionary>\n
Run Code Online (Sandbox Code Playgroud)\n

3. 添加包含以下内容的 myCommand.mm 文件:

\n
#import <Cocoa/Cocoa.h>\n\n@interface myCommand : NSScriptCommand\n@end\n\n@implementation myCommand : NSScriptCommand\n\n- (id)performDefaultImplementation {\n    NSString *sResult = @"";\n    NSString *sTitle = [self directParameter];\n    NSDictionary *asArgs = [self evaluatedArguments];\n    NSString *sSubTitle = [asArgs objectForKey:@"subtitle"];\n    NSString *sText = [asArgs objectForKey:@"text"];\n    sResult = [sResult stringByAppendingFormat:@"TITLE=%@ SUBTITLE=%@ TEXT=%@",sTitle,sSubTitle,sText];\n    NSUserNotification *n = [[NSUserNotification alloc] init];\n    n.title = sTitle;\n    if (![sSubTitle isEqualToString:@""]) {\n        n.subtitle = sSubTitle;\n    }\n    n.informativeText = sText;\n    [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n];\n    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n    return sResult;\n}\n\n@end\n
Run Code Online (Sandbox Code Playgroud)\n

4. 确保 AppKit.framework 是一个链接的二进制文件,就像平常一样。

\n

5. 编辑 Info.plist 文件并添加两个参数。(注意,下面是它们的原始键名称。)

\n

NSAppleScriptEnabled = YES
\nOSAScriptingDefinition = 命令.sdef

\n

6. 编译您的项目。然后,右键单击 XCode 中黄色 Products 文件夹下的产品,然后选择“在 Finder 中显示”。

\n

7. 单击您在 Finder 中看到的应用程序图标,然后按下左 Option 键。然后,在按住 Option 键的同时,转到 Finder 的“编辑”菜单并选择“复制路径名”。这会将应用程序的长路径名(在将其安装到 /Applications 之前)放在剪贴板上。

\n

8. 为了测试这一点,打开一个终端窗口,然后键入以下内容,将下面的路径替换为您的 Cocoa 应用程序的路径。

\n
osascript -e \'tell app "/crazy/long/path/Example.app" to notify user with title "My Title" subtitle "my sub" text "my text"\'\n
Run Code Online (Sandbox Code Playgroud)\n

9. 如果应用程序尚未打开,您应该会看到应用程序打开时带有一个停靠图标,然后在右上角您将看到侧边栏通知中出现一条通知。如果您已经安装了 GUI 应用程序,它还会有您的 GUI 应用程序的图标。请注意,如果您多次运行该命令,AppleScript 会很聪明,不会多次加载您的应用程序。另请注意,如果您单击侧边栏通知,它将打开您的应用程序屏幕(而不是仅将其图标化到扩展坞)。

\n

更多信息

\n

\xe2\x80\xa2 您可以修改步骤 2 和 3 中的代码以执行不同的命令并对其进行不同的操作。

\n

\xe2\x80\xa2 如果您需要的话,您可以修改您的 sdef (请参阅注释行)以返回结果。(非常适合调试!)

\n

\xe2\x80\xa2 你的 sdef 文件可以有单独的命令去不同的类。请参阅Apple 的示例以了解如何完成此操作。

\n

\xe2\x80\xa2 sdef 文件有一些奇怪的语法,例如“code”参数。更多信息请点击这里

\n

\xe2\x80\xa2 如果您有一个与 LaunchDaemon 结合使用的应用程序,但 LaunchDaemon 需要发送侧边栏通知,则此 AppleScript 连接非常有用。当然,有代码可以实现这一点,甚至还有一个技巧可以使 LaunchDaemon 图标显示您的应用程序图标而不是终端图标,但它不能做的一件事是,当单击该侧边栏通知,它会打开 GUI 应用程序。相反,当单击该侧边栏通知时,它会打开 LaunchDaemon,这是一个不希望的结果。因此,您可以使用此 AppleScript 技术来唤醒 LaunchDaemon 并通知其 GUI 应用程序同伴发送通知。这样,当单击侧边栏通知时,它会打开 GUI 应用程序,而不是 LaunchDaemon。

\n

\xe2\x80\xa2 让另一个应用程序发送一些 AppleScript 是很简单的:

\n
NSString *sScript = @"tell app \\"/Applications/Calculator.app\\" to activate";\nNSAppleScript *oScript = [[NSAppleScript alloc] initWithSource:sScript];\nNSDictionary *errorDict; \nNSAppleEventDescriptor *result = [oScript executeAndReturnError:&errorDict];\n
Run Code Online (Sandbox Code Playgroud)\n