My Tutorial

I got quite stuck in many ways with ASOC. I thought it may be beneficial to post a tutorial of things I would have found very useful back then for others beginning now. :slight_smile:

The script you will use is named [your app name]AppDelegate.applescript in the project library.

Firstly change

on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return my NSTerminateNow
	end applicationShouldTerminate_

to

on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return (current application's NSTerminateNow) as integer
	end applicationShouldTerminate_

In AppleScript Obj-C everything GUI related must have a link to your code to do this start off with

property parent : class "NSObject"

(to be honest I’m not sure why, this is what I know) then add property [your variable name] : missing value below for each GUI object you wish to interact with later in your code e.g.

property valwintext : missing value

missing value tells ASOC that this is a GUI property.

To create a GUI double click the .xib (usually MainMenu.xib) file in the project library, if you haven’t found this already, to open it in Interface Builder. Objects like text boxes, radio buttons, popups and buttons or even new windows can be dragged from the library window (library and inspector windows can be found in the Tools menu) and properties of these can be edited in the inspector.

To link a variable to a GUI element control click or right click drag from the blue cube in the little window named with [your app name] app delegate to the element and select your chose variable. Please note only properties from the last Xcode save will be listed. These can be referred to as IBOutlets (Interface Builder- IB)

To make buttons or really any clickable object do some action when clicked you must do something similar. In Xcode create a subroutine like normal but add _(sender) at the end, a bit like the terminate one and save. Now create the button(s) (multiple can be assigned to the same action) in Interface Builder, this time drag from the object TO the cube and select the subroutine. When you click a button when running your app it will run the linked subroutine. These can be referred to as IBActions.

Normal subroutines can still be used in the script but don’t have underscores.

Craig has great videos and pictures of this process.
Part 1: http://macscripter.net/viewtopic.php?pid=117489#p117489
Part 2: http://macscripter.net/viewtopic.php?pid=117608#p117608

As a little test link

on mysub_(sender)
display dialog "worked"
end mysub_

to a button, build and run and try clicking it.

ASOC commands to get or set values of GUI elements can be triggered with [your variable name]'s [command] or a tell [your variable name] statement, as a personal choice, I mainly use 's. Example:

myTextField's stringValue()

with myTextField linked as an IBOutlet to a Text Field. You could even try replacing “worked” with (myTextField’s stringValue()) as string. Complete basic example of what’s been covered so far:

script Testing_2AppDelegate

property parent : class "NSObject"
	property myTextField : missing value
	
	on mysub_(sender)
		display dialog (myTextField's stringValue()) as string
	end mysub_
	
	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened 
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return (current application's NSTerminateNow) as integer
	end applicationShouldTerminate_

end script

You will often need to unnecessarily coerce values between ASOC and AS. Also don’t make the mistake that text fields need to be named myTextField or that it needs to be capitalised -mytextfield.

All Obj-C commands are in the developer documentation in the help menu. To find a command look for the ‘NS’ name in Interface Builder library window under the the name of the object you want to use in the bottom section, then search it in the Xcode documentation window, then browse for what you want which will be handily be put in categories near the top. Sometimes you may need to view the parent for example stringValue is not in NSTextField but is in the parent NSControl (link at the top).

Obj-C commands listed in the documentation will be in the format of setIntValue: but to use in ASOC these commands must be changed. Replace : with _ and add brackets at the end if there are colons/underscores e.g.
setIntValue: setIntValue_()
insertItemWithTitle:atIndex: insertItemWithTitle_atIndex_()
intValue intValue()

If the command requires parameters it will have a colon (to change to an underscore) for each one, the brackets will contain these parameters e.g. setIntValue_(2) or insertItemWithTitle_atIndex_(“hello”,2) these vary and may or may not have a colon and therefore an underscore dependant on whether a parameter is required for example intValue() does not, setIntValue_() does because it needs a number to set something with. Often commands want a sender parameter where you can usually get away with putting in sender if contained in an IBAction subroutine other subroutines will need to be passed what the old IBAction sender was e.g.

on myActionSub_(sender)
otherSub(sender)
end myActionSub_

on otherSub(sender)
windowa's makeKeyAndOrderFront_(sender)
end otherSub

not

on myActionSub_(sender)
otherSub()
end myActionSub_

on otherSub()
windowa's makeKeyAndOrderFront_()
end otherSub

This will not work at all without a parameter, garbage could be used but I prefer to keep things clean.

If you look at commands in the documentation window (continuing example) intValue, setIntValue: (NSControl) and insertItemWithTitle:atIndex: you will notice under the title it has something like:

  • (int)intValue
    (int) tells you the kind of value to be returned (this is a getter)

  • (void)setIntValue:(int)anInt
    (void) tells you it will return nothing (this is a setter) the (int) after the colon (colon is the symbol for required parameter remember) is the kind of parameter required, generally ignore things like anInt after the bracket.

  • (void)insertItemWithTitle:(NSString *)title atIndex:(NSInteger)index
    Like before no returning value, title parameter must be a string, index parameter must be an integer.

Commonly used commands.

Text box commands:

Text View (NSTextView):
Read- |string|()
|| is used around Obj-C commands which are also in AS because the syntax takes AS as priority. || will not affect anything so don’t worry about using them if you are not sure
Write- setString_()

Text Field (NSTextField):
Read- stringValue()
Write- setStringValue_()

Window commands:

open- makeKeyAndOrderFront_()
There are variations as well. One of the sender parameters.
close- performClose_()
(sender too)

One more example this is still basic but more advanced than the last one.

script MultiplierAppDelegate
	
	property parent : class "NSObject"
	property number2val : missing value -- Text Field
	property number1val : missing value -- Text Field
	property resultval : missing value -- Text View
	
	on multiply_(sender) -- button
		set oldresult to resultval's |string|() as string
		set no1 to number1val's intValue() as integer
		set no2 to number2val's intValue() as integer
		set newresult to ((no1 * no2) as string) & "
" & oldresult
		resultval's setString_(newresult)
	end multiply_
	
	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened 
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return (current application's NSTerminateNow) as integer
	end applicationShouldTerminate_
	
end script

:slight_smile: