Online Book Reader

Home Category

AppleScript_ The Definitive Guide - Matt Neuburg [249]

By Root 1609 0
code, on the one hand, and the Cocoa key in the sdef, on the other—will cause scriptability to fail.

The reason Cocoa keys in the sdef are so crucial is that Cocoa scripting uses key-value coding to find its way through your code. Key-value coding (or KVC) is an informal protocol that takes advantage of Objective-C's dynamism and introspection. It uses a string as a key to hunt for names among your instance variables and methods. The object model is navigated by way of a path leading down from the application class. At every step of a path, your classes must be KVC-compliant (meaning that the right instance variables or methods are present) or things won't work.

In our application, so far, there is just one simple little path. The scriptability framework will start with the application class. It has a person element whose Cocoa key is "persons." So the framework looks in MyObject to see if it is KVC-compliant with respect to to the key "persons." Is it? Yes, because it has an instance variable named persons. That instance variable is an NSMutableArray; that's a built-in class which is itself KVC-compliant. The contents of this NSMutableArray are Person objects; that fits with the Cocoa key for this class, which says that everything in persons should be a Person. And Person is KVC-compliant with respect to "name," because it has a name accessor method and a setName: accessor method.

We build our application and run it, and point Script Editor at it, to test our scriptability—and it doesn't work! For example, we say:

tell application "Pairs"

get person 1

end tell

and we get an error message in the console:

[ valueForUndefinedKey:]: this class is not key value coding-

compliant for the key persons

The reason is simple: the very first step in the path is incorrectly set up. As our sdef says, the application class's Cocoa key is "NSApplication." But we want the path to start in MyObject, not in NSApplication. We must not change the Cocoa key for the application class; rather, we need a way to tell the scriptability framework to jump from NSApplication to MyObject as it descends the path. One very simple way to do this is to make MyObject the delegate of NSApplication; you can specify this by a connection in the nib. We must also write some code in MyObject announcing that it, as the application delegate, implements certain keys:

- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key {

if ([key isEqualToString: @"persons"]) return YES;

return NO;

}

We add that code to MyObject, which is now also NSApplication's delegate. We build and run the application, and we test it in Script Editor; lo and behold, it works!

tell application "Pairs"

count persons -- 2

name of person 1 -- "Jack"

name of person 2 -- "Jill"

name of every person -- {"Jack", "Jill"}

name of every person whose name ends with "k" -- {"Jack"}

exists person "Jack" -- true

exists person "Matt" -- false

delete person "Jack"

count persons -- 1

get name of person 1 -- "Jill"

set name of person 1 to "Mannie"

name of every person -- {"Mannie"}

end tell

This shows the advantage of starting with an application framework. We've added to an existing application no more than a couple of lines of code and a dozen lines of dictionary, and presto, we're scripting our application. We can get and set a property; we can count elements, delete an element, and test by property for the existence of an element; we can even use a boolean test specifier.

Having achieved this initial intoxicating success, we should consider some improvements and refactoring before proceeding any further:

Better accessors

So far, our code lends itself more or less by accident to KVC. For example, access to the person element is possible only because there happens to be an instance variable called persons in MyObject. We should implement our accessors in a more deliberate fashion, in accordance with the expectations of key-value coding and the scriptability framework.

Separate accessors

It will be wise to separate

Return Main Page Previous Page Next Page

®Online Book Reader