I am new to the world of Cocoa programming, and I want to add Applescript support to my application. The examples at Apple's website seem out of date.
我是Cocoa编程世界的新手,我想在我的应用程序中添加Applescript支持。 Apple网站上的例子似乎已经过时了。
How do I add Applescript support to my Cocoa application?
如何向我的Cocoa应用程序添加Applescript支持?
3 个解决方案
#1
42
-
If you want to send AppleScript from your application and need a sandboxed app, you need to create a temporary entitlement
如果要从应用程序发送AppleScript并需要沙盒应用程序,则需要创建临时权利
-
You need to add those two keys in your info.plist
您需要在info.plist中添加这两个键
<key>NSAppleScriptEnabled</key> <true/> <key>OSAScriptingDefinition</key> <string>MyAppName.sdef</string>
...of course you have to change "MyAppName" to your app's name
...当然,您必须将“MyAppName”更改为您应用的名称
-
Create a .sdef file and add it to your project. The further course now greatly depends on the needs of your application, there are:
创建.sdef文件并将其添加到项目中。更进一步的课程现在很大程度上取决于您的应用程序的需求,有:
- Class Elements (create an object from AppleScript)
- 类元素(从AppleScript创建对象)
- Command Elements (override NSScriptCommand and execute "verb-like" commands)
- 命令元素(覆盖NSScriptCommand并执行“类似动词”命令)
- Enumeration Elements
- 枚举元素
- Record-Type Elements
- 记录类型元素
- Value-Type Elements (KVC)
- 价值型元素(KVC)
- Cocoa Elements
- 可可元素
-
-
Go here to find a detailed description and many details on their implementation: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ScriptableCocoaApplications/SApps_script_cmds/SAppsScriptCmds.html
转到此处查找详细说明及其实施的许多详细信息:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ScriptableCocoaApplications/SApps_script_cmds/SAppsScriptCmds.html
-
I found working with Class and KVC Elements very complicated, as I just wanted to execute a single command, nothing fancy. So in order to help others, here's an example of how to create a new simple command with one argument. In this example it'll "lookup" one string like this:
我发现使用Class和KVC Elements非常复杂,因为我只想执行一个命令,没什么特别的。因此,为了帮助其他人,这里是一个如何使用一个参数创建一个新的简单命令的示例。在这个例子中,它将“查找”一个这样的字符串:
tell application "MyAppName" lookup "some string" end tell
-
The .sdef file for this command looks like this:
此命令的.sdef文件如下所示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd"> <dictionary title="MyAppName"> <suite name="MyAppName Suite" code="MApN" description="MyAppName Scripts"> <command name="lookup" code="lkpstrng" description="Look up a string, searches for an entry"> <cocoa class="MyLookupCommand"/> <direct-parameter description="The string to lookup"> <type type="text"/> </direct-parameter> </command> </suite> </dictionary>
-
Create a subclass of NSScriptCommand and name it MyLookupCommand
创建NSScriptCommand的子类并将其命名为MyLookupCommand
The MyLookupCommand.h
MyLookupCommand.h
#import <Foundation/Foundation.h> @interface MyLookupCommand : NSScriptCommand @end
The MyLookupCommand.m
MyLookupCommand.m
#import "MyLookupCommand.h" @implementation MyLookupCommand -(id)performDefaultImplementation { // get the arguments NSDictionary *args = [self evaluatedArguments]; NSString *stringToSearch = @""; if(args.count) { stringToSearch = [args valueForKey:@""]; // get the direct argument } else { // raise error [self setScriptErrorNumber:-50]; [self setScriptErrorString:@"Parameter Error: A Parameter is expected for the verb 'lookup' (You have to specify _what_ you want to lookup!)."]; } // Implement your code logic (in this example, I'm just posting an internal notification) [[NSNotificationCenter defaultCenter] postNotificationName:@"AppShouldLookupStringNotification" object:stringToSearch]; return nil; } @end
That's basically it. The secret to this is to subclass NSScriptCommand and override performDefaultImplementation. I hope this helps someone to get it faster...
基本上就是这样。这样做的秘诀是子类化NSScriptCommand并覆盖performDefaultImplementation。我希望这有助于某人更快地完成它...
#2
4
Modern versions of Cocoa can directly interpret the scripting definition (.sdef) property list, so all you need to do for basic AppleScript support is to create the sdef per the docs, add it to your "copy bundle resources" phase and declare AppleScript support in your Info.plist. To access objects other than NSApp, you define object specifiers, so each object knows its position in the scripting world's hierarchy. That gets you kvc manipulation of object properties, and the ability to use object methods as simple script commands.
现代版本的Cocoa可以直接解释脚本定义(.sdef)属性列表,因此您需要为基本的AppleScript支持做的就是根据文档创建sdef,将其添加到“复制包资源”阶段并声明AppleScript支持在您的Info.plist中。要访问NSApp以外的对象,可以定义对象说明符,以便每个对象都知道它在脚本世界的层次结构中的位置。这将使您对对象属性进行kvc操作,并将对象方法用作简单的脚本命令。
#3
1
A simple example to get you started,
一个简单的例子,让你开始,
place a script (named dialog) into the documents folder then you can run it from Xcode
将脚本(命名对话框)放入文档文件夹,然后您可以从Xcode运行它
NSArray *arrayPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = [arrayPaths objectAtIndex:0];
NSString *filePath = [docDirectory stringByAppendingString:@"/dialog.scpt"];
NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:nil];
[scriptObject executeAndReturnError:nil];
The nice thing about keeping the script external is the ability to edit it outside of Xcode. I would recommend adding the error checking if you did start editing as the applescript may not compile
保持脚本外部的好处是能够在Xcode之外编辑它。如果您确实开始编辑,我建议添加错误检查,因为AppleScript可能无法编译
maybe check with
也许检查一下
if(scriptObject.isCompiled){
#1
42
-
If you want to send AppleScript from your application and need a sandboxed app, you need to create a temporary entitlement
如果要从应用程序发送AppleScript并需要沙盒应用程序,则需要创建临时权利
-
You need to add those two keys in your info.plist
您需要在info.plist中添加这两个键
<key>NSAppleScriptEnabled</key> <true/> <key>OSAScriptingDefinition</key> <string>MyAppName.sdef</string>
...of course you have to change "MyAppName" to your app's name
...当然,您必须将“MyAppName”更改为您应用的名称
-
Create a .sdef file and add it to your project. The further course now greatly depends on the needs of your application, there are:
创建.sdef文件并将其添加到项目中。更进一步的课程现在很大程度上取决于您的应用程序的需求,有:
- Class Elements (create an object from AppleScript)
- 类元素(从AppleScript创建对象)
- Command Elements (override NSScriptCommand and execute "verb-like" commands)
- 命令元素(覆盖NSScriptCommand并执行“类似动词”命令)
- Enumeration Elements
- 枚举元素
- Record-Type Elements
- 记录类型元素
- Value-Type Elements (KVC)
- 价值型元素(KVC)
- Cocoa Elements
- 可可元素
-
-
Go here to find a detailed description and many details on their implementation: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ScriptableCocoaApplications/SApps_script_cmds/SAppsScriptCmds.html
转到此处查找详细说明及其实施的许多详细信息:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ScriptableCocoaApplications/SApps_script_cmds/SAppsScriptCmds.html
-
I found working with Class and KVC Elements very complicated, as I just wanted to execute a single command, nothing fancy. So in order to help others, here's an example of how to create a new simple command with one argument. In this example it'll "lookup" one string like this:
我发现使用Class和KVC Elements非常复杂,因为我只想执行一个命令,没什么特别的。因此,为了帮助其他人,这里是一个如何使用一个参数创建一个新的简单命令的示例。在这个例子中,它将“查找”一个这样的字符串:
tell application "MyAppName" lookup "some string" end tell
-
The .sdef file for this command looks like this:
此命令的.sdef文件如下所示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd"> <dictionary title="MyAppName"> <suite name="MyAppName Suite" code="MApN" description="MyAppName Scripts"> <command name="lookup" code="lkpstrng" description="Look up a string, searches for an entry"> <cocoa class="MyLookupCommand"/> <direct-parameter description="The string to lookup"> <type type="text"/> </direct-parameter> </command> </suite> </dictionary>
-
Create a subclass of NSScriptCommand and name it MyLookupCommand
创建NSScriptCommand的子类并将其命名为MyLookupCommand
The MyLookupCommand.h
MyLookupCommand.h
#import <Foundation/Foundation.h> @interface MyLookupCommand : NSScriptCommand @end
The MyLookupCommand.m
MyLookupCommand.m
#import "MyLookupCommand.h" @implementation MyLookupCommand -(id)performDefaultImplementation { // get the arguments NSDictionary *args = [self evaluatedArguments]; NSString *stringToSearch = @""; if(args.count) { stringToSearch = [args valueForKey:@""]; // get the direct argument } else { // raise error [self setScriptErrorNumber:-50]; [self setScriptErrorString:@"Parameter Error: A Parameter is expected for the verb 'lookup' (You have to specify _what_ you want to lookup!)."]; } // Implement your code logic (in this example, I'm just posting an internal notification) [[NSNotificationCenter defaultCenter] postNotificationName:@"AppShouldLookupStringNotification" object:stringToSearch]; return nil; } @end
That's basically it. The secret to this is to subclass NSScriptCommand and override performDefaultImplementation. I hope this helps someone to get it faster...
基本上就是这样。这样做的秘诀是子类化NSScriptCommand并覆盖performDefaultImplementation。我希望这有助于某人更快地完成它...
#2
4
Modern versions of Cocoa can directly interpret the scripting definition (.sdef) property list, so all you need to do for basic AppleScript support is to create the sdef per the docs, add it to your "copy bundle resources" phase and declare AppleScript support in your Info.plist. To access objects other than NSApp, you define object specifiers, so each object knows its position in the scripting world's hierarchy. That gets you kvc manipulation of object properties, and the ability to use object methods as simple script commands.
现代版本的Cocoa可以直接解释脚本定义(.sdef)属性列表,因此您需要为基本的AppleScript支持做的就是根据文档创建sdef,将其添加到“复制包资源”阶段并声明AppleScript支持在您的Info.plist中。要访问NSApp以外的对象,可以定义对象说明符,以便每个对象都知道它在脚本世界的层次结构中的位置。这将使您对对象属性进行kvc操作,并将对象方法用作简单的脚本命令。
#3
1
A simple example to get you started,
一个简单的例子,让你开始,
place a script (named dialog) into the documents folder then you can run it from Xcode
将脚本(命名对话框)放入文档文件夹,然后您可以从Xcode运行它
NSArray *arrayPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = [arrayPaths objectAtIndex:0];
NSString *filePath = [docDirectory stringByAppendingString:@"/dialog.scpt"];
NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:nil];
[scriptObject executeAndReturnError:nil];
The nice thing about keeping the script external is the ability to edit it outside of Xcode. I would recommend adding the error checking if you did start editing as the applescript may not compile
保持脚本外部的好处是能够在Xcode之外编辑它。如果您确实开始编辑,我建议添加错误检查,因为AppleScript可能无法编译
maybe check with
也许检查一下
if(scriptObject.isCompiled){