Developer Documentation
PATH  Mac OS X Documentation > Making Your Applications Scriptable

Making Your Applications Scriptable

Previous | Chapter contents | Next | Book PDF

Implement Scripting Methods

Overview

Setting aside the methods of the scripting classes (which are overridden only in special circumstances), two kinds of method implementations are commonly required for scripting, accessor methods and command handlers:

Accessor Methods

Key-value coding, which is the mechanism used for getting and setting object properties and for evaluating object references, looks first to use the accessor methods based on a key specified by a scriptable class in a class description. For example, if a class specifies a key of "name," key-value coding looks for accessor method name to get the value of the key and for accessor method setName: to set the value. If no accessor methods are implemented, it attempts to set or get the value of the instance variable directly.

However, sometimes what an accessor method does in the normal use of an application--getting and setting the value of an instance variable--doesn't work for scripting. The documents managed by a document-based application provide an example. When a script asks for an application's documents, NSDocumentController's documents method could be invoked to return all currently opened documents. But these documents are unordered in the returned NSArray and include both on-screen and off-screen documents. This is not what is required by scripting; AppleScript has the notion of a "front" document and a "last" document and this notion implies an ordering of documents visible on the screen. NSApplication therefore implements a method that, in response to a request for its documents, returns an NSArray that first contains all on-screen windows in their tier order and then all off-screen windows.

Another occasion for implementing an accessor method that does something more than simply set and get values is when it would be impractical to have objects at the level of granularity expected by AppleScript. For example, an AppleScript script can ask for the "characters" of a text document, but it would be quite expensive for an application to represent each character as an object. The Application Kit handles this request in a specially implemented "accessor" method.

Command Handlers

The description of a class (in a suite definition) includes a section for commands supported by the class. In this section you can either indicate that the default implementation (which is based on key-value coding) for a command is sufficient, or you can specify a method that you want to handle the command when it is executed. If the default implementation or handler for a command is insufficient for your purposes, you must specify and implement your own handler.

What You Must Do

Custom Accessor Methods

The procedure is no different than for specifying a class's actual accessor methods, except that the method you implement is used only in scripting.

  1. Specify the key of the attribute or relationship, along with supporting data (type, Apple event code, read-only flag), in a property-list format in the class description. (See " Creating Suite Definitions and Suite Terminologies " for procedure and examples.)
  2. Define accessor methods with names corresponding to the name of the key: set KeyName : and keyName . Then implement the methods to provide the necessary behavior that supplements or replaces the getting and setting of an instance-variable value.
  3. You can also override or implement extended key-value coding methods for better performance. For example, if it makes sense to perform some special array processing for your class, you could override valueAtIndex:inPropertyWithKey:.

Command Handlers

  1. Determine the command's return type and the type and key for each command argument. You can usually find this information by looking up the definition of the command in the Core suite definition ( Foundation.framwork/Resources/NSCoreSuite.scriptSuite ).
  2. In the Supported Commands section of the class description for the class implementing the command handler, assign the method to the command.
  3. "MyClass" = {
                "Superclass" = "NSCoreSuite.NSDocument";
                "Attributes" = {
                    // ...
    	    };
                "ToOneRelationships" = {
                   // ...
    	    };
                "SupportedCommands" = {
                    "NSCoreSuite.Save" "handleSaveCommand:";
    	    };
                "AppleEventCode" = "docu";
            };

    The method must have one and only one argument (and so in Objective-C must end in a colon).

  4. Implement the command handler. The signature of this method must be of the form:
  5. - (id)methodName:(NSScriptCommand *)command

    In the actual implementation code, get the command's arguments, handle the command, and return the expected value. If no return value is expected, return nil.

    - (id)handleSaveCommand:(NSScriptCommand *)command {
        NSDictionary *args = [command evaluatedArguments];
        NSString *file = [args objectForKey:@"File"];
        NSNumber *ftype = [args objectForKey:@"FileType"];
    
        if (file) {
            /* handle command here */
        }
        return nil;
    
    }

Making Your Applications Scriptable

Previous | Chapter contents | Next | Book PDF