This is something I am slowly compiling. I already had extensive experience with Applescript and Objective-C before using ASOC, and this represents the bare minimum I needed to get up and running with my first application.
.applescript vs .scpt
Applescripts are managed in Xcode with the extension .applescript, which is (nicely) a plain text file, but then when the application is complied, they get converted to .scpt. This is important to remember when linking one script file to another in code because using the .applescript extension will result in the file not being found.
.applescript Template
Xcode does not have a way to create an .applescript file from within the file create dialog, so this is based on the template offered by AppDelegate given in a new project.
(* ScriptName.applescript ApplicationName Created by __Name__ on MM/DD/YY. Copyright (c) YYYY __MyCompanyName__. All rights reserved. *) -- TODO: Insert properties and subroutines here
Debugging
The only tool available is logging to the debugger. Breakpoints do not work.
Calling ObjC methods
- Use the current application keyword for calls to ObjC class methods
- Argument names are appended with _ (an underscore) and argument values are place in the same order within the parentheses. There needs to be a one-for-one relationship between the arguments and the underscores
- If a method has no arguments, then no underscores are required.
Method with one argument
[textBox setStringValue:@"FOO"];
…becomes this…
textBox's setStringValue_("FOO")
Method with two arguments
NSString *filePath = [NSBundle [mainBundle pathForResource:fileName ofType:@"txt"]];
…becomes this…
set filePath to current application's NSBundle's mainBundle's pathForResource_ofType_(fileName, "txt") as text
Method with NO arguments
NSColor *black = [NSColor blackColor];
…becomes this…
tell current application's NSColor to set black to blackColor()
Binding Interfaces
In the following example…
- All interface elements need a property set to missing value. Cocoa will fill in the blanks
- NSTextField:outlet binds to property textField
- NSButton:selector binds to on runShowFoo_(sender)
- Note the underscore in the method name denoting an argument sender
script OCAppDelegate property textField : missing value property runButton : missing value on runShowFoo_(sender) textBox's setStringValue_("FOO") end runShowFoo_ end OCAppDelegate
Instantiating NSObject-based Classes
”AppleScriptObj-C Explored” only describes adding a class via a nib file, but that is only useful for higher-level controller classes. I find that more often than not, I am calling classes either via class methods—for example, [NSString string];
— or via the classic [[foo alloc] init];
. The following describes how to instantiateNSObject
-based objects directly in ASOC code.
Given a class OCFoo
…
OCFoo.h
#import @interface OCFoo : NSObject + (OCFoo *)foo; - (NSString *)getValue; @end
OCFoo.m
#import "OCFoo.h" @implementation OCFoo - (id)init { self = [super init]; if (self) { // implementation } return self; } + (OCFoo *)foo { return [[self alloc] init]; } @end
Instantiating with a Class method
set foo to current application's OCFoo's foo
Instantiating with [[foo alloc] init];
I have not figured out a way to make this into one line just like in ObjC. There is a part of me that thinks there isn’t a way to do it and that we are stuck with two lines.
set foo to current application's OCFoo's alloc set foo to init of foo