6

I'm trying to add some scripting functionality to a Cocoa app that I've written. I've created an sdef (Scripting Definition File) for my project. So far I have been successful in accessing object children (elements) with AppleScript but I cannot for the life of me figure out how to call methods (commands).

Here is my sdef file.

<suite name="mySuite" code="mSUI" description="My Application Suite">
    <class name="application" code="capp" description="Top level scripting object.">
        <cocoa class="NSApplication"/>
        <!-- I can access these elements fine -->
        <element description="Test children." type="child" access="r">
            <cocoa key="myChildren"/>
        </element>
        <!-- Cannot seem to call this method :( -->
        <responds-to command="testmethod">
            <cocoa method="exposedMethod:"/>
        </responds-to>
    </class>
    <class name="child" code="cHIL" description="A Child." plural="children">
        <cocoa class="Child"/>
        <property name="name" code="pnam" description="The child name." type="text" access="r">
            <cocoa key="name"/>
        </property>
    </class>
    <command name="testmethod" code="tEST" description="Execute the test method" />
</suite>

Here are my controller class implementations (this is the delegate of my application)

MyController.h

#import <Cocoa/Cocoa.h>

@interface MyController : NSObject {
    NSMutableArray* myChildren;
}
// Some Methods

@end

MyController+Scripting.m

#import "MyController+Scripting.h"

@implementation MyController (Scripting)

// This works when I'm accessing the myChildren 
- (BOOL)application:(NSApplication*)sender delegateHandlesKey:(NSString*)key { 
    NSLog(@"Key = %@", key);
  return ([key isEqualToString:@"myChildren"]);
}
// This does NOT work...
- (void)exposedMethod:(NSScriptCommand*)command {
    NSLog(@"Invoked Test Script Method %@", [command description]);
}

@end

Lastly, the AppleScript I am trying is:

tell application "MyApplication"
    testmethod
end tell

which responds with "AppleScript Error - The variable testmethod is not defined."

Any ideas what I'm doing wrong here? I feel like I'm missing something simple but my Googling doesn't seem to be turning up anything helpful.

Quinn Taylor
  • 44,553
  • 16
  • 113
  • 131
nrj
  • 1,701
  • 2
  • 22
  • 37
  • Perhaps I'm missing something, but is this a Cocoa (OS X) app or a Cocoa Touch (iPhone) app? iPhone apps don't support AppleScript. – sbooth Jul 24 '09 at 01:34
  • The asker clarified that UIController was the (poorly-chosen) name of a custom application controller/delegate class, so I updated the code to remove confusion. – Quinn Taylor Jul 29 '09 at 16:21
  • 1
    Don't command codes have to be 8 characters long? (It should be 4 MacRoman characters for the suite code, then 4 more for the specific command code. But I think Cocoa Scripting doesn't give a crap and allows any 8 character string that isn't already claimed.) – CTMacUser Jun 24 '14 at 04:46

3 Answers3

2

I just posted a detailed solution on how to add a command with argument here: https://stackoverflow.com/a/10773994/388412

In short: I think you should subclass NSScriptCommand and override -(void)performDefaultImplementation rather than exposing a method in your controller. At least that's what I distilled from the docs:

"This command is a subclass of NSScriptCommand, containing one method, performDefaultImplementation. That method overrides the version in NSScriptCommand"

… and it works fine for me, see my linked answer for details.

Community
  • 1
  • 1
auco
  • 9,329
  • 4
  • 47
  • 54
2

Things look mostly right, but the code for the <command/> should be a two-part code (eight characters) and not four.

Ben Stiglitz
  • 3,994
  • 27
  • 24
1

(I've actually never added scriptability to a Cocoa app, so take my stab in the dark with a grain of salt.)

The first thing I would guess is that exposedMethod: takes a parameter, but I don't see where one might be specified in your sdef or AppleScript. In fact, it looks like AppleScript is treating testmethod as a variable, not a command. (Maybe it should be something like "testmethod with ..." instead?) You may need to define a <parameter> or <direct-parameter> element for the command in the sdef.

Also, wouldn't you need an object to call the method on? Since your controller is the application delegate, I'm not sure of the intricacies there, but might AppleScript try to invoke testMethod: on NSApplication instead of your delegate?

I'm guessing you've looked at Apple's sample code and other resources, but if not, here are a few links that may help:

Good luck!

Quinn Taylor
  • 44,553
  • 16
  • 113
  • 131
  • 1
    The parameter to that method is an instance of NSScriptCommand, which encapsulates any Apple Event parameters that may have been passed along. All script-command methods take one of those as an argument. – Ben Stiglitz Jul 30 '09 at 16:44