I'm looking for a way to execute an Applescript file from within a Mac App. I've made previous mac applications that use NSAppleScript *script = [[NSAppleScript alloc] initWithSource: @"MY_CODE"]];
, but my applescript is quite lengthy and I'd like to just be able to reference that file as part of my project, and pipe in the contents of it (or just directly execute the file from within my app).
Thank you!
To run user-supplied AppleScripts outside the sandbox (10.8+), use NSUserAppleScriptTask
To run .scpt files embedded in your application bundle, or user-supplied scripts in 10.7 or earlier, use NSAppleScript.
NSUserAppleScriptTask and NSAppleScript are both a bit lame, mind you. Neither provides automatic data conversion between Cocoa and AS types, which means a lot of manual mucking with NSAppleEventDescriptors to pass parameters and results. NSAppleScript instances provide partial persistency support: the script's properties retain state across multiple handlers calls, but there's no way to save the altered script back to disk so any changes are lost once it's dealloced. And NSUSerAppleScriptTask is a strictly one-shot affair, so script state doesn't persist at all between calls.
For deeper integration between embedded AppleScript and ObjC code within your app bundle, use AppleScriptObjC (10.6+):
ASOC is a two-way bridge similar to PyObjC or RubyCocoa, allowing you write your AppleScript code within script objects that then appear to your ObjC code as regular Cocoa classes, allowing ObjC code to call AS handlers and AS code to call ObjC methods. Common ObjC and AS types (ints, doubles, NSStrings, NSArrays, etc) are automatically wrapped/converted when crossing the bridge, so requires no additional work other an occasional cast on the AS side.
ASOC is not perfect (Apple's own docs suck, bridging isn't toll-free, and glitches aren't unknown), but for interacting with scriptable apps from ObjC it is the best of an otherwise rather rubbish set of choices.
Why not put your compiled script or script text within your package and then use NSAppleScript's initWithContentsOfURL:error: method?
For example:
NSError * error = NULL;
NSURL * resourceURL = [[NSBundle mainBundle] resourceURL];
NSURL * urlOfScript = [resourceURL URLByAppendingPathComponent: @"MyApplescript.scpt"];
NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL: urlOfScript error: &error];
if(script == NULL)
{
NSLog( @"could not instantiate script at %@ - %@", [urlOfScript absolutePath], [error localizedDescription] );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With