TweetFollow Us on Twitter

AppleScript in Cocoa

Volume Number: 18 (2002)
Issue Number: 05
Column Tag: AppleScript in Cocoa

It's Now Easier to Support AppleScript Suites in Cocoa

by Don Briggs donbriggs@mac.com

AppleScript Studio is now available to developers. This product will open Mac OS X development to many more people, and they will build applications relying on AppleScript. If their applications are to interoperate with yours, your Cocoa applications and their underlying frameworks must also support AppleScript.

This article is for Cocoa Objective-C developers. It will review the concepts and techniques necessary to implement AppleScript support. It will show the steps necessary to revise an existing example to support AppleScript. It introduces a new application for composing AppleScript suites —SuiteModeler. A compressed disk image

EZCocoaAppleScript.dmg.gz is available for download at: http://homepage.mac.com/donbriggs/FileSharing.html

The disk image contains:

  • this document as EZCocoaAppleScript.rtfd;
  • KVC_Demo —a simple Project Builder tool project that demonstrates Key-Value Coding;
  • DotSuite.scriptDocument, a SuiteModeler document (a wrapper/directory) containing the suite definition and suite terminology files for a Cocoa AppleScript suite, and a directory of ‘naive' Objective-C files to support the suite.
  • ScriptableDotView —the example application we will build in this article as a Project Builder project;
  • sample output documents (bigRed.dot, littleBlue.dot) in XML form; and
  • a test script that drives our ScriptableDotView application.

Overview

In this article, we will compose an AppleScript suite from scratch using SuiteModeler. This suite will serve as a statement of requirements, and the Objective-C files that SuiteModeler emits will serve as a starting point for our implementation. From these Objective-C files we will implement the classes and commands of the suite. We will build the document-based application, ScriptableDotView, that supports the suite. To emphasize KVC, we will also employ it to provide XML persistence for our documents in just a few lines of code. We will repackage the data-handling classes of our suite as a reusable framework. Finally, we will test our implementation using AppleScript.

Introducing SuiteModeler

The reader is invited to download SuiteModeler version 1.7.2 (or later) and run it in Demo mode. You need not buy a license to follow this article —the disk image provides all the required output files. SuiteModeler's Demo mode also permits you to inspect other suites and to check them for conflicts (see below). In licensed mode, SuiteModeler will save the suites you compose.

Suites were Hard to Compose

Nominally we use Apple's "PropertyList Editor" application

file:///Developer/Applications/PropertyListEditor.app

to compose Cocoa suites. It supports the property list format, but the following difficulties remain:

We need to produce two files, the *.suiteScript and *.scriptTerminology. Each provides its own "projection" of the underlying classes, but these projections are not "orthogonal"—the two files must maintain a nontrivial correspondence. But "PropertyList Editor" edits each file separately.

There are lots of key words, and their values must obey rules. You must read and apply

file:///Developer/Documentation/Cocoa/ProgrammingTopics/Scripting

Some symbols refer to others, but unresolved references are not immediately obvious.

There are some annoying or confusing aspects of the Cocoa documentation: we find two meanings for the word "Property," for instance.

Some entries are generic and could be "calculated" from others, but "PropertyList Editor" does not provide such help —it's a general application.

Finally, when inspecting a suite (or rather, one half of a suite) in "PropertyList Editor," much of the text we see amounts to repeated key words.

In short, we could use some better tooling.

Suites were Hard to Support

Given a composed suite, the developer hoping to support AppleScript in Cocoa must make sure the Objective-C classes correspond to the suite. In the phrase often used by College-level Math texts, the process is "tedious but straight-forward." And "by inspection" —those same texts also say "by inspection" a lot. Admittedly, your second suite will be much easier, but your first one will require close reading of several lengthy documents. Wouldn't it be nice if your first suite were easy and it "just worked"?

Suites were Hard to Debug — Conflicts!

Even after a script compiles, it may not run as expected; the trouble often lies in the relationships of Apple Event Codes and external names. A given code can associate with multiple external names, but a given external name must associate with a unique code. If your suite matches an Apple Event Code with an external name that already exists in another suite loaded at run-time (NSCoreSuite and NSTextSuite come to mind), scripts written against your suite may crash or yield unexpected results. Such conflicts have stumped experts —and for good reason. To the author's present knowledge, this "gotcha" remains undocumented by Apple. (Greg Titus of OmniGroup for pointed out this "gotcha" to the author. Thanks, Greg.)

Composing and Supporting Cocoa Suites Just Got Easier

SuiteModeler is available as a demo at http://homepage.mac.com/donbriggs/FileSharing.html

You are invited to download it and use it to inspect Cocoa suites. The download site provides a screenshot of the suite from the Create application from Stone Design.

The Cocoa suites you compose will often build on NSCoreSuite and NSTextSuite. You'll find these among SuiteModeler's "Open Recent" menu items. When using SuiteModeler to inspect a suite or check one for conflicts, be sure to open any suites it depends on.

Background on AppleScript in Cocoa

To implement AppleScript support in Cocoa, you need to know about two important supporting concepts —the design pattern known as Model-View-Controller (MVC), and the technique known as Key-Value Coding (KVC). If you have not seen these Cocoa documents before,

file:///Developer/Documentation/Cocoa/ProgrammingTopics/AppDesign/AppDesign.1.html

file:///Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/KeyValueCoding/index.html

this article will introduce you to the main ideas we need to understand to support AppleScript. We also need to focus on document-based applications as described in

file:///Developer/Documentation/Cocoa/ProgrammingTopics/AppDesign/AppDesign.d.html

You will find that when we use NSApplication and NSDocument, we get lots of AppleScript support for free.

Regular readers of MacTech and those long interested in AppleScript for Cocoa already know of Andrew Stone's earlier article, "Adding AppleScript Support to Cocoa Apps." http://www.mactech.com/articles/mactech/Vol.16/16.07/AppleScripttoCocoa/

There, Andrew discussed MVC, KVC, and AppleScript support in the Sketch example. Andrew's article also showed us how to add a "Save as AppleScript..." capability to Sketch.

Sketch is quite a large example, and presents its AppleScript suite with little explanation. A reader previously unfamiliar with Sketch might find it daunting. This article takes a bare-bones approach to building a suite —the ratio of explanation to code is quite different. We start from a simpler example, DotView, which is found at file:///Developer/Examples/AppKit/DotView.

Newcomers might compare DotView and Sketch for size and complexity, then take a relaxing deep breath.

Model-View-Controller — MVC

The Model-View-Controller design pattern comes to us from the Smalltalk tradition. MVC suggests that we partition our objects into those that treat the "real data" —the "Model" part; those that provide a human interface to the data —the "View"; and other stuff necessary to glue the Model and View together —the "Controller" part.

Generally, design patterns identify commonly occurring archetypes of interoperating components. They bear "prior knowledge" at the conceptual and architectural level. The main benefit of following the MVC design pattern is the reusability of the components we build.

The Cocoa frameworks were designed to support MVC. Using Cocoa, we find we can often make the "Model" part into a stand-alone framework and use it again for other purposes. Our "Model" frameworks commonly build on the Foundation framework —Foundation comprises mostly "Model" classes that encapsulate "real data." The AppKit framework provides classes that support the "View" and "Controller" parts. Often, we can get most or all the "View" part from Interface Builder. For ScriptableDotView, Cocoa provides much of the Controller part with no extra code. If you avoid storing "model" information in "view" objects (for instance, don't store a boolean in a button's state), you'll find that the Cocoa frameworks provide a natural basis for the MVC design pattern. When we add AppleScript capability, we add a powerful way to control the "Model" part.

Key-Value Coding —KVC

Key-Value Coding amounts a simple discipline that matches the declaration of an instance variable to the declarations of its getter and setter methods. When we follow those rules in a class for an instance variable, we implement KVC in that class for that variable. Given an instance variable of primitive type ( BOOL, char, short, unichar, int, float, double, ...) or struct (NSRange, NSPoint, NSSIze, NSRect, ... ) we have as a declaration

   type _xyz;    // Let type be one of: 
      // BOOL, char, short, unichar, int, float, double, ..., NSRange, NSPoint, NSSIze,             
      // NSRect, ... and as accessors
   -(type)xyz;
   -(void)setXyz: (type)xyz;

Given an instance variable that is an object, we have as a declaration

   MyClass *_abc;
and as accessors
   -(MyClass*)abc;
   -(void)setAbc: (MyClass*)abc;

You may neglect the underscore prefix in the name of the instance variable, but then you should change the name of the argument in the corresponding setter method.

The KVC_Demo project is a simple one-class tool project that shows KVC at work. You can use KVC to reduce the complexity of your code, independent of AppleScript support. The Cocoa documentation on scripting recommends that you "define the set of keys each scriptable class supports." The author suggests that you use class methods to provide collections of related keys. In KVC_Demo, the class method +[ModelClass kvcKeys] provides such an array of keys.

DotView Revisited

Copy the example DotView project to a convenient place, compile it, run it, and marvel at it. The DotView example application shows us how a subclass of NSView can respond to a mouse click with a drawing operation. The project has a single class, DotView—pristine simplicity. But with apologies to DotView's author, Professor Ozer*, the author points out that DotView does not follow MVC nor does it support KVC. Newcomers might breathe a sigh of relief now. If presently your code falls short too, you'll find yourselves in fine company.

(*Ali Ozer only professes to be the head of the AppKit —he is the only remaining original engineer from the first four that worked on NeXTSTEP in the late eighties.)

Consider the class DotView from the perspective of MVC. It descends from NSView but has instance variables and accessor methods for the only "real data" of the application. It's both the "View" and the "Model." DotView has no need for a "Controller" part, then. We'll revise the project along the lines of MVC.

As for KVC, we see that there are instance variables named "color" and "radius" with the accessors

   - (IBAction)setRadius:(id)sender;
   - (IBAction)setColor:(id)sender;

But these method signatures do not support KVC —each "setter" method should take as its single argument a variable of the same type as its associated instance variable. To support KVC, we need instead

   -(float)radius;
   -(void)setRadius: (float)radius;
and
   -(NSColor*)color;
   -(void)setColor: (NSColor*)color;
We'll fix that, too.

On to ScriptableDotView.app

Let us imagine that we work as developers for the company called "My Great Software, Inc." and that the prototype application, DotView, has successfully promoted an idea for a marketable application. Marketing loves it, Management is committed to it, and now we have to deliver on its promise. ScriptableDotView will be our product, an industrial-strength revision of the prototype. A high-level meeting has produced a set of requirements. (We always need requirements. How else will we know when we're done?)

Requirements

    [0] ScriptableDotView reproduces the look and feel of DotView.

    [1] ScriptableDotView has just one kind of document, and it saves the state of a "Dot" —its radius, position, and color.

    [2] The document must persist in XML form. Management loves buzz-word compliance. (XML really is useful, though.)

    [3] The document must permit AppleScript access to its dot's radius, position, and color.

    [4] The document must support an AppleScript command, ReCenter, to place the dot in the center of the view area.

    [5] And Marketing suspects that a few other related applications could follow on, so we should encapsulate the "real data" in a framework that we can use again.

An Internal Requirement

The ReCenter command is the simplest kind of command; it takes no arguments and returns void. While we're exploring AppleScript support, it seems prudent to demonstrate support for a command that takes an argument and returns a value. We'll add a command to the Dot class that does something simple and clearly useless to ScriptableDotView: it will take a string argument and return a string with the same characters in the opposite order. We'll spend just a few minutes under Management's radar on this, but this exercise will improve our confidence in supporting AppleScript. We add to our requirements:

    [6] The Dot class will temporarily support the Reverse command (a command with one argument and a return value).

Design Overview

At the core of things, we have the concept of the dot, the "real data" of the application—the "Model" in an abstract sense. We'll have a class, Dot, to manage the dot's radius, position, and color. Also, we'll have a subclass of NSDocument, DotDocument, to manage a single instance of Dot. The separation between the dot and its document may seem contrived, but often a document manages a collection of model objects, but here, we have just the single element. (Often, a descendent of NSDocument acts as a sort of Model-Controller. Contrast this to NSWindowController, which is a kind of View-Controller.) As for the rest of the "Controller" part, we could conceivably subclass NSDocumentController and NSWindowController, but for the sake of expediency, we'll force into the DotDocument class any leftover model-controller methods we need. We'll package the Dot and DotDocument classes in a scriptable framework, , to provide the "Model" and "Controller" parts of our MVC design. The "View" part must derive from the prototype to preserve its look and feel. Here, this means that we can copy the *.nib file of the prototype and make a few modifications. As a novel departure, we will start with an AppleScript suite as a statement of requirements and then drive the implementation to support our suite.

DotSuite

Our suite, DotSuite is conceptually very simple: it has two classes: an instance of the DotDocument class serves as a container for an instance of the Dot class. DotDocument has just one read-only attribute, its dot. Dot has four attributes: its x and y positions, its radius and its color. DotSuite has the two Commands, but no Enumerations or Synonyms.

Ideally, Dot should have one attribute of type NSPoint instead of two attributes of type float, the x and y positions. However, as presently documented, Cocoa AppleScript suites support only primitives (BOOL, short, int, float, ...) and objects as attributes. We look forward to support for structs such as NSPoint and NSRect. Curiously, if you examine NSCoreSuite, you'll find a dictionary called ValueTypes with one entry pairing the key QDRect with the string value qdrt. Also, the NSWindow class has a property named boundsAsQDRect and type NSData. As of Mac OS 10.1.3, the author has found no documentation explaining these entries. We'll follow the lead of the Sketch example and proceed with the pair of floats (as instances of NSNumber).

The AppleScript Suite —DotSuite

To compose this suite, launch SuiteModeler and edit its empty suite document. The screen shots below show what to type in. In the "Preferences" panel, choose the "Cocoa/E-R/EOModeler" nomenclature to see these tab labels. SuiteModeler combines the definition and terminology in one document and presents it as a tree of table views. Wherever a node has multiple children, the children appear as tabs in a tab view. The root of the tree, the suite itself, is a special case and appears as a the "Suite" tab among its children. Also, an extra "Summary" tab provides a flattened summary, useful for sorting out more complicated suites and finding conflicts.

The Suite Itself

The suite itself has an internal and an external name, an Apple Event code, and a description. Fill in these four fields as shown. (Throughout this exercise, we will neglect entries in the description fields. SuiteModeler makes it easy to add them, and they can be extremely useful to the AppleScript authors who will incorporate your application in their scripts. However, descriptions are the least of our immediate concerns.)

pastedGraphic.tiff ¬

Apple Event code entries always have four characters, and SuiteModeler enforces that constraint. Apple has reserved the space of codes comprising all combinations of four lower-case letters, so always use at least one upper-case letter in your codes. (Beware: if the trailing characters are spaces, that fact won't be apparent in "PropertyList Editor" unless you select the entry.)

Commands

We start with the two Commands. In the "Commands" tab, use the upper "+" button to add thwo entries. Their names appear initially as MyCommand, and MyCommand_1. Enter the values for the fields in the upper table as shown (use any string for the descriptions). Rename them and enter the other fields as shown. Notice that SuiteModeler generates some fields for you: given a name, it guesses the external name. Given an external name, it guesses the plural and sometimes, it can correctly guess the appropriate Apple Event Code value.

1__#$!@%!#__pastedGraphic.tiff ¬

The ReCenter command takes no arguments and yields no result. It simply re-centers the dot in the view and serves as an example of the simplest kind of command. With the Reverse command selected, use the "+" button in the lower table to add its string argument as shown. The Reverse takes a string as an argument and returns a string of the same characters in the opposite order (just to demonstrate an AppleScript command with an argument and a return value).

Classes

Our suite has two classes. In the "Classes" tab, use the upper "+" button to add two entries. They appear with MyClass and MyClass_1 in the "name" column, again with default entries in the other columns.

The DotDocument Class

In the first entry, type in DotDocument in the "name" column. SuiteModeler generates its external name and plural, so these entries are in gray. Type in docu for its Apple Event Code, and NSCoreSuite.NSDocument as its superclass. Here, we're using the code docu from the core suite, so it's all lower-case. The superclass entry appears in red denoting an unresolved reference. (To resolve the reference, open the NSCoreSuite from the "Open Recent" menu. This entry then appears in black.) Type in an entry for the description. With the DotDocument row still selected, choose the "Attributes" tab in the lower half of the split view. Then use the lower "+" button to add an attribute. Set its name to dot, its type to Dot, its code to xDot, and set the "[r/o]" or Read-Only column entry to Y or y. SuiteModeler will complete the entry. SuiteModeler constrains the entries for the sex and number columns in a similar way —just type in the first letter of your choice.

The Dot Class

The entries for the Dot class follow from the screen shot. (Once you've typed in its name, the reference to it in the DotDocument class should appear in black.) Notice that its external name, dot, appears in blue (multiple references), and its code, xDot, appears in grey (default) to indicate that all (here, both) items with the same external name have the same code.

2__#$!@%!#__pastedGraphic.tiff ¬

3__#$!@%!#__pastedGraphic.tiff ¬

Tying Classes to Commands

For each of the two classes, add supported commands as shown. Had we not defined these commands first in the "Commands" tab, their names would have appeared in red—perhaps a little alarming for an introduction. Again, given the name for a supported command, SuiteModeler calculates a method name.

4__#$!@%!#__pastedGraphic.tiff ¬
5__#$!@%!#__pastedGraphic.tiff ¬

Tool Tips

The headers of the columns of all the table views in SuiteModeler provide tool tip support. Each column's tool tip associates a key with the text from the corresponding tables of the documentation in

file:///Developer/Documentation/Cocoa/ProgrammingTopics/Scripting/SuiteDefs

The exception is the "ext. name" column. It shows the synthetic "HumanReadableName" instead of "Name," which is the key associated with the "name" column.

Conflicts —a Demonstration

As an experiment, temporarily make a conflict of codes and external names. Change the code for the dot class from xDot to yDot then switch to the "Summary" tab. You'll see that suddenly the codes and external names involved in the conflict appear in red. If you try to save the suite document in such a state, SuiteModeler will warn you. Change it back to xDot.

6__#$!@%!#__pastedGraphic.tiff ¬

Some readers may choose to complete this exercise successfully, then build in a conflict and explore the consequences.

Save

If you've not bought a license, use the result supplied. Otherwise, save the result as DotSuite, using the default choice, document wrapper, for the output file format. The wrapper contains the definition and terminology files. Check it against the version supplied.

You could also reproduce the work in the "PropertyList Editor" application, but you'll have to read the documentation more carefully to produce a working suite that way. Choose a non-trivial existing suite, say NSCoreSuite to compare SuiteModeler and "PropertyList Editor." You'll find the SuiteModeler presentation more compact and unified (after all —using "PropertyList Editor," you have to open two documents, the definition and the terminology). Certainly, when you compose your own suite, SuiteModeler's validation, automatic generation of default values, and cross-referencing features will save you some headaches.

The ‘Naive' Objective-C Files

SuiteModeler also emits a directory of Objective-C files when it saves a suite document. Open all the Objective-C files in the document wrapper now. Each class in your suite results in a *.h and a *.m file. A single *.h file declares any enumerations in the suite. For each class, it provides instance variables and accessors for each attribute/property and property/element (only the "getter" methods for the read-only cases). It also declares and provides a base implementation for each supported command, declaring and extracting any command arguments. It also declares and implements a class method that provides an array of keys useful for KVC. It also provides some support for object specifier methods.

Implementation —Step by Step

SuiteModeler will not emit all the code necessary to implement your suite, and the class files will likely not compile as emitted. In each case, you'll need to add or modify a few lines to import the parent class, and to import or declare any other classes referenced (perhaps using "@class" in the *h files). You may need to import these from your own frameworks. However, SuiteModeler has saved you lots of typing. As a developer, you must provide the underlying logic specific to your "Model" —that's why "My Great Software, Inc." pays you the big bucks. For each class, Dot and DotDocument, we explain the few lines we modify to compile the naive file. Then we add categories of "Model" logic to each.

First we'll build and test a simple application. Then we will repackage it by moving two classes into a framework. We will also make the framework scriptable. We'll re-compile and test the repackaged code. Then we'll drive the resulting compiled application with an AppleScript suite.

Start with a Cocoa Document-based project. It provides a generic "MyDocument" class—keep it. Add the Dot and DotDocument files to the "Classes" group, "by copy" from the suite document wrapper. We'll move them into a framework later. For the methods below, find their implementations in the completed project.

In this exercise, we will rely on several categories in separate files. A category encapsulates a group of related methods. The author hopes that by isolating these categories in separate files, the reader will find it easier to track differences using FileMerge. (The XML methods for NSDictionary can prove generally useful.) Otherwise, this exercise takes the notion of categories and protocols perhaps a bit too far.

Initial Details —Imports and Declarations

    [1] In Dot.h, add

       @class DotDocument;
    

    just before the "@interface ..." line.

    [2] In DotDocument.h, comment out the line

       #import "NSDocument.h" 
    

    We get reference to that class when we import the <Cocoa> framework.

    [3] Also in DotDocument.h, add

       @class Dot;
    

    just before the "@interface ..." line.

    [4] In DotDocument.m, import the Dot class. Add

       #import "Dot.h"
    

    just after the existing import.

    [5] in Dot.m, import DotDocument.h similarly.

The changes so far should permit you to compile the ‘naive' files, but the compiler will warn about unused variables.

Add a Category of XML Methods to NSDictionary

Add to your projects by copy the files NSDictionary+XMLMethods.h and *m (provided in the ScriptableDotView project). You may find this category generally useful. See Brian Webster's post on the OmniGroup Cocoa Dev list, www.omnigroup.com/mailman/archive/macosx-dev/2001-January/008625.html

One might reasonably expect Cocoa API for this. As things stand, we drop down into Carbon.

Repackage the MyDocument Methods as a Category

Project Builder provides some Objective-C code in the generic "MyDocument" class. Convert the MyDocument class to be the DotDocument+Subclassing category. Rename the *.h and *m files, change the import statement in the *.m file, and change the @interface and @implementation lines to support the category. They become

   @interface DotDocument (Subclassing) 

and

   @implementation DotDocument (Subclassing)

(and delete the pair of curly braces in the *.h file). Also in the *.m file, change the windowNibName method to return @"DotDocument".

Augment DotDocument+Subclassing For XML Persistence

In the *.m file, import NSDictionary+XMLMethods.h and Dot.h. In the methods

   dataRepresentationOfType:

and

   loadDataRepresentation:ofType:

add the few lines necessary to provide XML persistence. Notice that KVC makes this really compact. Compare with SKTDrawDocument in the Sketch example. Sketch resorts to the methods -[SKTGraphic propertyListRepresentation] and +[SKTGraphic graphicWithPropertyListRepresentation] and their overriding implementations in the subclasses of SKTGraphic. If we had comparable subclasses here, we would only need to override the +kvcKeys method in each subclass (assuming we had already written the matching get and set methods anyway). Remember that any code you don't have to write is code you don't have to debug, either.

Add DotDocument+ModelControlling as a Category

This category comprises two methods. One writes "Model" information to the "View," and the other writes "View" information to "Model." Such a pair of methods often proves useful. Import the DotDocument+ModelControlling.h category.

Add the NSView+DotViewing Protocol

This protocol declares one method. It will become part of the framework. The application will have a DotView class that conforms to it.

Add Model-Controller Instance Variables and Logic to DotDocument

In DotDocument.h add these instance variables

   IBOutlet NSView *_view;
   IBOutlet NSSlider *_slider;
   IBOutlet NSColorWell *_colorWell;

and declare these methods:

   -(IBAction)viewAction: (id)sender;
   -(void)modelChanged;

The viewAction method responds to user interactions—mouse clicks and drags, and setting the color—and passes the information to the document, which sends it to the model. The modelChanged method signals the "View" that it must re-draw to reflect changes in the "Model." In Document.m, import the DotDocument+ModelControlling.h category. It comprises two methods. One writes "Model" information to the "View," and the other writes "View" information to the "Model." In this class, they're both empty—we'll override them in DotDocument to do useful work. Add the awakeFromNib method to initialize the "View." Find the implementations for these methods in the completed project. Add an init method that initializes the document's instance of the Dot class. Add the awakeFromNib method to initialize the "View."

Augment the Class Implementations with Custom "Model Logic"

Declare and implement the initWithDocument: method, and import "DotDocument.h". DotDocument's handleReCenterScriptCommand: and Dot's handleReverseScriptCommand: both require few-liner modifications. We can't save NSColor in property list form directly. As in the Sketch example, we'll have to archive NSColor as NSData. We're not free to replace the naive color accessors —AppleScript needs them—so we'll supply two more to access the color attribute as archived NSData. Be sure to change colorKey to colorDataKey so our kvcKeys method can support XML persistence. We'll come to the remaining new instance variable and the initializer later.

Steal Your Interface

Open the MainMenu.nib document of the DotView example and copy its Window component (it has the view, color well, and slider). Open your project's MyDocument.nib file, delete its Window component and replace it with the one from DotView. Drag the DotDocument.h file from Project Builder's files pane onto the MyDocument panel, so Interface Builder can parse the file. Set the File's Owner to be DotDocument. Delete MyDocument from your nib. Disconnect the actions for the slider and color well, and connect them to the File's Owner, choosing the viewAction: method. Save the result as DotDocument.nib.

Adjustments for Fit and Finish

Choose your project's "Targets" tab. In the "Application Settings" tab and using the "Expert" settings, set the document class to be DotDocument and set the file extension to be dot. Choose the "simple" settings and set the document's extension to dot.

First Test

The application should compile and launch after you have made these changes. It should be able to save and open its documents in XML form.

Make it Scriptable

Under the application target's application settings tab, choose the "expert" settings and add a new sibling called NSAppleScriptEnabled. Set its value to the string YES. Add to the Resources group the files DotSuite.scriptSuite and DotSuite.scriptTerminology from the DotSuite.suiteDocument file wrapper provided, using the "by copy" option. Localize the terminology file (select it in the Files pane and "Show Info"). Be sure that these files are checked as part of the application target. Recompile. Now, Script Editor should be able to browse to your project's "build" directory and open your application's dictionary. Also, the script provided should properly drive your application.

One More Step —Repackage the "Model" classes as a Framework

Refer to the article http://www.cocoadevcentral.com/tutorials/

"Frameworks Within the App Bundle" by Brian Christiansen, Cocoa Dev Central

Following the article, set the framework's installation location to the path:

   @executable_path/../Frameworks

and add the linker flag

   -seg1addr 0x10000000

as detailed there.

From the "Project" menu, choose "new target." Choose its type to be Cocoa framework. Set the name of the framework target to be Dot. In the Target pane, set the Dot target to be ‘under' ScriptableDotView (that is, to make ScriptableDotView, you must first have made Dot. )

In the File pane, add a new Group called and select it. Move the NSView+DotViewing protocol and the Dot and DotDocument classes into the new group. Remove them from the application target and add them to the framework target. Be sure to set those headers to "Public." Similarly, move the DotSuite.scriptSuite and DotSuite.scriptTerminology files to the framework. You'll also need to drag the Dot.framework element in the "Products" group in the Files pane to the application target's "Files & Build Phases" tab's "Frameworks & Libraries" fields.

QED

Compile and run the application. If it fails, compare your project against the supplied ScriptableDotView project. You should be able to verify that the requirements have been met.

Conclusion

We've used the SuiteModeler application to compose a Cocoa AppleScript suite as an expression of requirements. We've developed a framework and application on it that support our AppleScript suite, starting from the Objective-C files SuiteModeler emitted, adjusting only the imports and declares, and adding just a few lines of "Model" logic. We have used Key-Value Coding both in the support of our suite and to simplify XML persistence of our document-based application. We have used AppleScript to test our implementation. Readers can now build their own script-enabled Cocoa applications and frameworks more easily.


 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Macs Fan Control 1.5.14 - Monitor and co...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
VueScan 9.7.96 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
FileMaker Pro 19.6.1 - Quickly build cus...
FileMaker Pro is the tool you use to create a custom app. You also use FileMaker Pro to access your app on a computer. Start by importing data from a spreadsheet or using a built-in Starter app to... Read more
Duet 3.1.0.0 - Use your iPad as an exter...
Duet is the first app that allows you to use your iDevice as an extra display for your Mac using the Lightning or 30-pin cable. Note: This app requires a iOS companion app. Release notes were... Read more
Firefox 107.0.1 - Fast, safe Web browser...
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
War Thunder 2.21.1.91 - Multiplayer war...
In War Thunder, aircraft, attack helicopters, ground forces and naval ships collaborate in realistic competitive battles. You can choose from over 1,500 vehicles and an extensive variety of combat... Read more
Numbers 12.2.1 - Apple's spreadshee...
With Apple Numbers, sophisticated spreadsheets are just the start. The whole sheet is your canvas. Just add dramatic interactive charts, tables, and images that paint a revealing picture of your data... Read more
DEVONthink Pro 3.8.7 - Knowledge base, i...
DEVONthink is DEVONtechnologies' document and information management solution. It supports a large variety of file formats and stores them in a database enhanced by artificial intelligence (AI). Many... Read more
Drive Genius 6.2.3 - $79.00
Drive Genius features a comprehensive Malware Scan. Automate your malware protection. Protect your investment from any threat. The Malware Scan is part of the automated DrivePulse utility. DrivePulse... Read more
VLC Media Player 3.0.18 - Popular multim...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more

Latest Forum Discussions

See All

‘Genshin Impact’ Version 3.3 Pre-Install...
Following the reveal of the release date and more for Genshin Impact (Free) version 3.3 ‘All Senses Clear, All Existence Void’, HoYoverse showcased the Genius Invokation TCG that arrives this week in the update. | Read more »
TouchArcade Game of the Week: ‘Sling Min...
The world of PC games has always blown my mind because there’s just SO MUCH stuff out there that it’s not uncommon at all for there to be a game that’s well-liked and well-reviewed, and seemingly quite popular with a solid fanbase, and have it be... | Read more »
SwitchArcade Round-Up: Reviews Featuring...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 2nd, 2022. So, today turned out a little quieter than the usual Friday. It was so quiet, in fact, that I decided to pen a few reviews. The Knight Witch, Railbound, and Donut... | Read more »
Blue Archive reveals its latest event st...
Nexon has announced the new update for Blue Archive, under the name of An Unconcealed Heart. Featuring a battle between two academies, the story will follow a group struggling to gain recognition, and will bring three new students to recruit. [... | Read more »
Dead Cells+ Is Out Now on Apple Arcade a...
Following the major update for Dead Cells on iOS and Android a few days ago, Playdigious has brought Dead Cells+ () to Apple Arcade. As an App Store Great, Dead Cells+ includes all prior paid DLC and content updates. It also has exclusive mobile... | Read more »
SwitchArcade Round-Up: ‘Romancing SaGa’,...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 1st, 2022. Wow, December. We’re already at the last month of the year? Phew. I have a lot of work to finish in the next few weeks. As for today, we’ve got a little news, a... | Read more »
‘Railbound’ Update Now Available Adding...
One of our favorite puzzlers released this year is Railbound from Afterburn Games, which hit in early September and earned our Game of the Week recognition for being an absolutely ace logic puzzler. The goal is to place rail pieces down in order to... | Read more »
The Seven Deadly Sins: Grand Cross celeb...
Netmarble Corporation has pulled out all the stops to celebrate the 3 and a half year anniversary of The Seven Deadly Sins: Grand Cross. The Grand Cross 3.5th Year Anniversary the Ultimate One, a rather wordy title, brings with it a brand new... | Read more »
‘Skullgirls Mobile’ Major Update 5.2 Out...
Developer Hidden Variable pushed out a major update for Skullgirls Mobile (Free) a few hours ago. The version 5.2 update brings in Black Dahlia (before the console and PC game), Retakes, XP Treats, free gifts, and more. Since launch, Skullgirls... | Read more »
Out Now: ‘Disgaea 4’, ‘Romancing SaGa: M...
Each and every day new mobile games are hitting the App Store, and so each week we put together a big old list of all the best new releases of the past seven days. Back in the day the App Store would showcase the same games for a week, and then... | Read more »

Price Scanner via MacPrices.net

Holiday Sale: Apple AirPods Pro for only $199...
Amazon has new 2022 AirPods Pro in stock and on sale for $199.99 shipped as part of their Holiday sale. Their price is $50 off Apple’s MSRP, equaling their Black Friday price, and it’s the lowest... Read more
New Holiday Sale: Apple retailers are offerin...
Several Apple retailers lowered prices on 10.9″ iPad Airs overnight to lows of $100 off MSRP starting at $499. Their prices are the lowest available for iPad Airs anywhere this Holiday season right... Read more
New Holiday sale at Amazon: Take $50 off Appl...
Amazon has Apple’s new 10th-generation iPads in stock and on sale, for the first time, for $50 off MSRP starting at only $399. Their discount applies to all models and all colors. With the discount,... Read more
Holiday Sale: Get an 8.3″ Apple iPad mini for...
Sams Club has 10.9″ 64GB iPad minis on Holiday sale for $80-$100 off MSRP through December 7, 2022. With their discount, prices start at $399 — the cheapest price for a new iPad mini from any of the... Read more
Sams Club Holiday December Event sale: Apple...
Apple AirPods Max headphones are on sale at Sams Club for $110 off MSRP ($439) as part of their December Event sale, ending on December 7, 2022, valid for all colors. Sale price for online orders... Read more
Apple’s 10.2″ 64GB 9th-generation iPads are o...
Sams Club has 9th-generation 64GB iPads on Holiday sale for $60 off MSRP through December 7, 2022. With their discount, prices start at $259 — the cheapest price for a new iPad from any of the Apple... Read more
11″ 128GB WiFi M2 iPad Pro on sale for $749,...
B&H Photo has the new 11″ 128GB WiFi M2-powered iPad Pro (in Space Gray or Silver) on Holiday sale for $749 including free 1-2 day shipping to most US addresses. Their price is $50 off MSRP and... Read more
Find the best Holiday sale price on an iPad u...
We’ve updated our iPad Price Trackers with the latest information on the new 10th-generation iPads, M2-powered iPad Pros, M1 iPad Airs, iPad minis, and 9th generation iPads from Apple’s authorized... Read more
Apple retailers are offering $100-$150 Holida...
Apple retailers have posted their most-recent Holiday sale prices on 13″ MacBook Airs. Take up to $150 off MSRP on M2-powered Airs with these sales with prices starting at only $1099. Free shipping... Read more
Holiday Sale: Apple’s 14″ MacBook Pros with M...
B&H Photo is offering $200-$300 discounts on Apple’s 14″ MacBook Pros with M1 Pro CPUs as part of their Holiday 2022 sale, with prices starting at $1799. Free 1-2 day shipping is available to... Read more

Jobs Board

Support Technician II - *Apple* Support - O...
…problems and acting as a liaison between customers and resolving groups. As an Apple Technical Specialist, you will be supporting many of our popular Apple Read more
*Apple* Electronic Repair Technician - PlanI...
…a highly motivated individual to join our Production Department as an Apple Electronic Repair Technician. The computer repair technician will diagnose, assemble, Read more
Lead Developer - *Apple* tvOS - Rumble (Uni...
…earnings, and positive sentiment About the role: We are looking for a Lead Apple tvOS Developer to join our application engineering team to expand our video centric Read more
Tier 1 Endpoint Engineer - *Apple* - Red Ri...
…Desk on site, at our Client's location, with a focus on support to Apple products. This position will handle technical support requests directly from customers and Read more
Product Manager II - *Apple* - DISH (United...
…you will be doing We seek an ambitious, data-driven thinker to assist the Apple Product Development team as our new Retail Wireless division continues to grow and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.