Struggling with basic AppleScript support

Dragan Milić milke at mac.com
Tue Feb 6 09:17:31 PST 2007


Hello everyone,

I'm definitely getting frustrated with AppleScript and adding support  
for it in a Cocoa application. First, I had a problem with  
"AppleScript Dictionary Caching" gotcha, but now that it's solved I  
really struggle with a very basic support for AppleScript. So, after  
spending the whole day trying to figure out what I was doing wrong, I  
saw no other way further than to ask on this list. I'll try to  
explain as detailed as possible what I did, so I apologise in advance  
to those not liking long posts.

My application is NOT a document based one. Let's suppose its name is  
iPet. The principal class is NSApplication. An application controller  
MyPetController is the delegate of the NSApp. Each pet is represented  
by an instance of class MyPet, which is the subclass of NSObject, and  
has got two attributes: name and species, both of NSString type. All  
pets are recorded in an NSMutableArray pets, which is an instance  
variable of the MyPetController.

MyPetController correctly implements -pets: get accessor method (set  
accessor is not implemented, there's no way to set all pets, one can  
only add them to the pets array):

- (NSArray *)pets
{
     return [NSArray arrayWithArray:pets];
}

Also, in MyPetController I've implemented required delegate method:

- (BOOL)delegateHandlesKey:(NSString *)key
{
     return [key isEqualToString:@"pets"];
}

MyPet class correctly implements both get and set accessors for its  
attributes:

- (NSString *)name
{
     return name;
}

- (void)setName:(NSString *)aName
{
     [aName retain];
     [name release];
     name = aName;
}

- (NSString *)species
{
     return species;
}

- (void)setSpecies:(NSString *)aSpec
{
     [aSpec retain];
     [species release];
     species = aSpec;
}

Finally, this is how .scriptSuite and .scripTerminology (I need to  
support 10.3) files look like (don't worry, they are not long):

iPetSuite.scriptSuite:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http:// 
www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
     <key>AppleEventCode</key>
     <string>iPet</string>
     <key>Classes</key>
     <dict>
         <key>NSApplication</key>
         <dict>
             <key>AppleEventCode</key>
             <string>capp</string>
             <key>Superclass</key>
             <string>NSCoreSuite.NSApplication</string>
             <key>ToManyRelationships</key>
             <dict>
                 <key>pets</key>
                 <dict>
                     <key>AppleEventCode</key>
                     <string>Pett</string>
                     <key>Type</key>
                     <string>iPetSuite.MyPet</string>
                 </dict>
             </dict>
         </dict>
         <key>MyPet</key>
         <dict>
             <key>AppleEventCode</key>
             <string>Pett</string>
             <key>Attributes</key>
             <dict>
                 <key>name</key>
                 <dict>
                     <key>AppleEventCode</key>
                     <string>Name</string>
                     <key>Type</key>
                     <string>NSString</string>
                 </dict>
                 <key>species</key>
                 <dict>
                     <key>AppleEventCode</key>
                     <string>Spcs</string>
                     <key>Type</key>
                     <string>NSString</string>
                 </dict>
             </dict>
             <key>Superclass</key>
             <string>NSCoreSuite.AbstractObject</string>
         </dict>
     </dict>
     <key>Name</key>
     <string>iPetSuite</string>
</dict>
</plist>

iPetSuite.scriptTerminology:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http:// 
www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
     <key>Classes</key>
     <dict>
         <key>NSApplication</key>
         <dict>
             <key>Name</key>
             <string>application</string>
             <key>PluralName</key>
             <string>applications</string>
         </dict>
         <key>MyPet</key>
         <dict>
             <key>Attributes</key>
             <dict>
                 <key>name</key>
                 <dict>
                     <key>Description</key>
                     <string>The pet's name.</string>
                     <key>Name</key>
                     <string>name</string>
                 </dict>
                 <key>species</key>
                 <dict>
                     <key>Description</key>
                     <string>The pet's species.</string>
                     <key>Name</key>
                     <string>species</string>
                 </dict>
             </dict>
             <key>Name</key>
             <string>pet</string>
             <key>PluralName</key>
             <string>pets</string>
         </dict>
     </dict>
     <key>Name</key>
     <string>iPet Suite</string>
</dict>
</plist>

So, let's say the script looks like this:

tell application "iPet" to get pets

I can confirm that the delegate method -delegateHandlesKey: is called  
with key="pets" and I can observe that the -pets; accessor method of  
MyPetController really gets called. So, in the Script Editor output  
I'd expect to see something like (if pets array contains e.g. four  
instances of MyPet class):

{pet 1 of application "iPet", pet 2 of application "iPet", pet 3 of  
application "iPet", pet 4 of application "iPet"}

But instead I see:

{application "iPet", application "iPet", application "iPet",  
application "iPet"}

It's like I get four instances of NSApplication class, not MyPet. Add  
another pet to the array and as a result I get file instances of  
NSApplication class!

When executing:

tell application "iPet" to get last pet

Again I can confirm that the delegate method -delegateHandlesKey: is  
called with key="pets" and I can observe that the -pets; accessor  
method of MyPetController really gets called. Instead of expected  
result:

{pet 4 of application "iPet"}

I get nothing. Of course, if I try something like:

tell application "iPet" to set name of last pet to "Dingo"

I get the script error, since MyPet object is not returned.

There's probably some stupid thing that I'm overlooking, but I just  
can't figure out what that'd be. If I compare my .scriptSuite  
and .scriptTerminology files to those of TextEdit application, they  
look almost exactly the same. Same goes for the relevant code of  
MyPetController and TextEdit controller class. But still, TextEdit  
can be scripted successfully.

Someone please put me out of my misery :-)

Regards,
Milke




More information about the MacOSX-dev mailing list