AppleScript-based "classes" may be used directly from Objective-C and other languages via the AppleScript-ObjC bridge (10.6+).
AppleScript-ObjC allows you to use ObjC for all your general programming stuff, and only call into AppleScript via the AppleScript-ObjC bridge for the IPC stuff.
From the POV of your ObjC code, your AppleScript-based ASOC 'classes' are more or less indistinguishable from regular ObjC classes. It requires a bit of fiddling to set up, and you'll pay a bit of a toll when crossing the bridge, but given the crippled, unreliable nature of the alternatives, it's the least horrid of the supported options for anything non-trivial.
Assuming you've already got an existing ObjC-based project, here's how to add an ASOC-based class to it:
In Targets > APPNAME > Build Phases > Link Binary With Libraries, add AppleScriptObjC.framework.
In Supporting Files > main.m
, add the import and load lines as shown:
#import <Cocoa/Cocoa.h>
#import <AppleScriptObjC/AppleScriptObjC.h>
int main(int argc, const char * argv[]) {
[[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];
return NSApplicationMain(argc, argv);
}
To define an ASOC-based class named MyASClass
that's callable from ObjC, create a MyASClass.h
interface file that declares its public methods:
// MyASClass.h
#import <Cocoa/Cocoa.h>
@interface MyASClass : NSObject
// Note: C primitives are only automatically bridged when calling from AS into ObjC.
// AS methods with boolean/integer/real parameters/results must declare NSNumber*:
- (NSNumber *)square:(NSNumber *)aNumber;
@end
along with a MyASClass.applescript
file containing its implementation:
-- MyASClass.applescript
script MyASClass
property parent : class "NSObject"
on square_(aNumber)
return aNumber ^ 2
end square_
end script
Because the MyASClass
class doesn't have an ObjC implementation, the linker can't link your ObjC code to it at build-time. Instead, use NSClassFromString()
to look up the class object at run-time:
#import "MyASClass.h"
...
MyASClass *stuff = [[NSClassFromString(@"MyASClass") alloc] init];
Otherwise it's pretty much indistinguishable from a native ObjC class in normal use:
NSNumber *result = [stuff square: @3];
NSLog(@"Result: %@", result);
As of 10.10, AppleScript can use Cocoa frameworks in any Script Editor-based script. This makes it easy for Python and other languages that have Objective-C bridges to call AppleScript directly, without having to package everything as an Xcode app.
Stick one or more compiled .scpt
files containing AppleScript-ObjC "classes" into a folder, e.g.:
use framework "Foundation"
use scripting additions
script MyASClass
property parent : class "NSObject"
--
on test()
activate
display dialog "Hello from AppleScript!"
end test
end script
then just use it from Python like this:
from Foundation import NSBundle, NSClassFromString
import AppleScriptObjC
NSBundle.alloc().initWithPath_(FOLDERPATH).loadAppleScriptObjectiveCScripts()
MyASClass = NSClassFromString(u"MyASClass") # get the ASOC class...
MyASClass.alloc().init().test() # ...then instantiate and call it