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.


 
AAPL
$102.13
Apple Inc.
+1.24
MSFT
$44.87
Microsoft Corpora
-0.14
GOOG
$571.00
Google Inc.
-6.86

MacTech Search:
Community Search:

Software Updates via MacUpdate

Get Lyrical 3.8 - Auto-magically adds ly...
Get Lyrical auto-magically add lyrics to songs in iTunes. You can choose either a selection of tracks, or the current track. Or turn on "Active Tagging" to get lyrics for songs as you play them.... Read more
Viber 4.2.2 - Send messages and make cal...
Viber lets you send free messages and make free calls to other Viber users, on any device and network, in any country! Viber syncs your contacts, messages and call history with your mobile device,... Read more
Cocktail 7.6 - General maintenance and o...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
LaunchBar 6.1 - Powerful file/URL/email...
LaunchBar is an award-winning productivity utility that offers an amazingly intuitive and efficient way to search and access any kind of information stored on your computer or on the Web. It provides... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
BBEdit 10.5.12 - Powerful text and HTML...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more
Microsoft Office 2011 14.4.4 - Popular p...
Microsoft Office 2011 helps you create professional documents and presentations. And since Office for Mac 2011 is compatible with Office for Windows, you can work on documents with virtually anyone... Read more
TextWrangler 4.5.10 - Free general purpo...
TextWrangler is the powerful general purpose text editor, and Unix and server administrator's tool. Oh, and also, like the best things in life, it's free. TextWrangler is the "little brother" to... Read more
BitTorrent Sync 1.4.72 - Sync files secu...
BitTorrent Sync allows you to sync unlimited files between your own devices, or share a folder with friends and family to automatically sync anything. File transfers are encrypted. Your information... Read more
Cyberduck 4.5.2 - FTP and SFTP browser....
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more

Latest Forum Discussions

See All

ALONE... (Games)
ALONE... 1.0.1 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.1 (iTunes) Description: ALONE is a handcrafted, intense survival journey through space. Navigate caves, rip through rocky debris, dodge rocks and comets... | Read more »
Almightree: The Last Dreamer (Games)
Almightree: The Last Dreamer 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: The world is shattering and you are the only hope to restore the balance. A thrilling and challenging 3D puzzle... | Read more »
The Nightmare Cooperative (Games)
The Nightmare Cooperative 1.1 Device: iOS Universal Category: Games Price: $3.99, Version: 1.1 (iTunes) Description: Fiendishly difficult! Adorably cute! Utterly engrossing!How much gold can you get before your entire team is... | Read more »
Mobile Convolution (Music)
Mobile Convolution 1.0.0 Device: iOS Universal Category: Music Price: $9.99, Version: 1.0.0 (iTunes) Description: | Read more »
Invaders! From Outer Space Review
Invaders! From Outer Space Review By Rob Thomas on August 27th, 2014 Our Rating: :: RETRO NOSTALGIAUniversal App - Designed for iPhone and iPad It’s a shame that Invaders! doesn’t offer deeper gameplay, as this retro-inspired... | Read more »
Spooklands Review
Spooklands Review By Jennifer Allen on August 27th, 2014 Our Rating: :: ONE-TOUCH SHOOTERUniversal App - Designed for iPhone and iPad One-touch simultaneously controls your direction and your weapon in this unique arena shooter.   | Read more »
Heroes of Order & Chaos Add Twitch I...
Heroes of Order & Chaos Add Twitch Integration, New Heroes, and More Posted by Ellis Spice on August 27th, 2014 [ permalink ] | Read more »
Foodie Yama Review
Foodie Yama Review By Jennifer Allen on August 27th, 2014 Our Rating: :: BRIEFLY HOOKSUniversal App - Designed for iPhone and iPad Foodie Yama will draw you in for a brief while, and you’ll never be entirely sure why.   | Read more »
Spotify Connect Turns One, Now Supports...
Spotify Connect Turns One, Now Supports New Devices Posted by Ellis Spice on August 27th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
The Rise of PicsaStock and How You Can M...
We all take plenty of photos, right? That’s the joy of having a reasonably powerful camera in your pocket, thanks to your trusty iPhone and a bevy of similarly useful apps. Wouldn’t it be great to make some money out of those snaps? While your... | Read more »

Price Scanner via MacPrices.net

12-Inch MacBook Air Coming in 4Q14 or 2015 –...
Digitimes’ Aaron Lee and Joseph Tsai report that according to Taiwan-based upstream supply chain insiders, Apple plans to launch a thinner MacBook model either at year end 2014 or in 2015, and that... Read more
Sapphire Screen “Most Wanted” iPhone 6 New Fe...
According to the ‘uSell.com iPhone Most Wanted Survey’ — a representative survey of 1,000 U.S. smartphone users conducted by used iPhone marketplace uSell.com — close to half of all smartphone users... Read more
The iPad’s Real Competitive Challenger (Not S...
It’s been my contention for some time that the iPad is suffering from something of an identity crisis, and I suspect that may be a factor in slackening sales this year. Apple can’t seem to decide... Read more
13-inch 2.6GHz/256GB Retina MacBook Pro on sa...
B&H Photo has the 13″ 2.6GHz/256GB Retina MacBook Pro on sale for $1379 including free shipping plus NY sales tax only. Their price is $120 off MSRP. Read more
Life Inventory iOS Apps – Learn to Know Thyse...
James Hollender’s Life Inventory apps s are now on sale with 20% off thru Labor Day, 09/01/2014. This is a great opportunity to get started on that Moral Inventory you’ve been putting off doing for... Read more
Pocket Watch, LLC. Reveals Cloud Server For P...
Beaumont, Texas based Pocket Watch, LLC. has announced the availability of its new ActivePrint Cloud Server Powered by Raspberry Pi. With this small standalone box almost any USB printer or available... Read more
902it Simplifies Area Code Changes For Nova S...
The east coast Canadian provinces of Nova Scotia and Prince Edward Island are phasing in 10 digit telephone dialing, to be fully in place by November, in order to accommodate a second area code to... Read more
Boomerang iPad Stand Mounts Your iPad Anywher...
Boomerang, a Mountable Stand with Multiple Viewing Angles, is now available for iPad Air. Boomerang combines several functions that aim to expand your iPad’s potential in one, elegant product. The... Read more
Retina MacBook Pros available starting at $10...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available starting at $929. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros (4GB RAM/... Read more
Apple 27-inch Thunderbolt Display (refurbishe...
The Apple Store has Apple Certified Refurbished 27″ Thunderbolt Displays available for $799 including free shipping. That’s $200 off the cost of new models. Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.