Introduction
Although many areas of the Cocoa framework are accessible through AppleScript in AppleScript Studio, many areas are not. You may also find using Objective-C is often easier than an equivalent AppleScript. The way we access Objective-C from AppleScript is with a call method.
The Reason For This Tutorial
As I began to use call methods I found very little information on how it is implemented. Apple has a short example here but does not go into much detail. There have been some questions and answers on the mail lists but nothing of great detail.
I am not an experienced Objective-C developer so the information below is from personal trial-and-error and examining the example application Multi-Language that Apple provides.
With that said, let’s get started! Hope you enjoy!
Download the source code here.
Accessing Your Classes
In this tutorial we will cover how to access the classes and methods you write. Most of the example code I have seen covers (+)class methods but not (-)instance methods. This is not very helpful because you cannot access instance variables or instance methods from a (+)class method.
How it works
- AppleScript sends a call method to an Objective-C class we’ll call the “controller.”
- The “controller” instantiates an object of another Objective-C class that you have written and calls one of its’ methods.
- The new object performs the requested method actions and passes return values, if any, back to the “controller” which passes them on to the calling AppleScript.
This means that anything you want the Objective-C class to know about, you have to explicitly send it that information. For example, if you want your Objective-C method to set a text field on your layout to a certain value, you need to send the text field along as a parameter: {text field “textField” of window “main”}
What a call method looks like
Call Method No Parameters
This will call the method “logSomething” with no parameters. The method logSomething does not have a trailing colon because it has no parameters. It is also not required to explicitly state the class in your method call but it is probably good form to do so.
AppleScript Code:
Objective-C Code:
Call Method With Parameters
This will call the method “appendString:withString:” with two parameters.
This method has parameters so each ends with a colon.
Parameters are supplied as a list so they are enclosed in {}.
AppleScript Code:
Objective C Code:
New Project
Create a new AppleScript Studio project and call it “Call Methods” or whatever you prefer.
Create a “Controller” Class
Create a new Objective C class and name it Controller.m. Check the box that also creates the .h file. The Controller class will act as our messenger. We send messages to the Controller then the Controller contacts the appropriate class to get the job done. Once the job is completed the Controller returns the results.
The “Controller.h” File
The multi-language example provided by Apple states the best way to access instance methods in your classes is to add a category to the NSApplication class.
The “Controller.h” File
Define a method in “Controller.h”
This is the method we will call from AppleScript.
The “Controller.m” Class
Add the method to “Controller.m”
Create a “Model” Class
Now that we have our “Controller” class setup we need to create the class that is going to do the work.
In our example we will call this class “Model.”
Go ahead and make that class now.
The “Model.h” Class
In “Model.h” we define the method that will do the actual work. You can use the exact same method name we used in the Controller class here in the Model. I chose to prefix the name with MODEL to distinguish them but it is not necessary. Normally I use the same name in both places for simplicity and to reduce errors.
The “Model.m” Class
Let’s create our method.
AppleScript
In our AppleScript file add the following in an awakeFromNib handler.
display dialog (call method "appendString:withString:" ¬
with parameters {"Feed me", "Seymour!"})
Now Build and Run!
Final result!
Final Thoughts
This is a very simple example and by itself is completely useless. What I want to convey is the process in which it is performed. Once you understand that all communication is directed to the Controller class and all information you want the Controller class to know about must be included in the parameters. Then it becomes easier to implement more complicated tasks.
Using this technique you can add as many Objective-C classes as you like and use the Controller class to talk to all of them.
Happy coding!
Craig