Here's what I have:
1) Include the proper "permissions" entries in the 'Info.plist
- 'Scriptable': YES
- 'Scripting definition file name': myApp.sdef
2) Include the element "element" tag within a class extension "element" tag:
`<class-extension extends="application" description="The application and top-level scripting object.">
<!-- various property tags go here -->
<element type="object item" access="r">
<cocoa key="theseObjects"/>
</element>
</class-extension>`
3) Include the element class tag:
<class name="object item" code="Objs" description="Application 'too many' object collection" plural="object items" inherits="item"> // I don't believe 'inherits' name is critical for AS to work
<cocoa class="ObjectItem"/>
</class>
4) Include the delegate method that forwards 'NSApplication' scriptability support to its delegate:
- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key {
if ([key isEqualToString:@"theseObjects"]) {
return YES;
}
return NO;
}
5) Create a 'ObjectItem' class and put the object specifier there:
- (NSScriptObjectSpecifier *)objectSpecifier {
NSScriptObjectSpecifier *containerRef = nil;
NSScriptObjectSpecifier *specifier = [[NSNameSpecifier alloc] initWithContainerClassDescription:[NSScriptClassDescription classDescriptionForClass:[NSApp class]] containerSpecifier:containerRef key:@"theseObjects" name:@"objectName"];
return [specifier autorelease];
6) Post the KVO accessor method within the Application's delegate:
- (NSArray *)theseObjects;
{
ObjectItem *thisObject = [[ObjectItem new] autorelease];
NSArray *thisArray = [NSArray arrayWithObject:thisObject];
return thisArray;
}
}
7) Create an AppleScript that returns objects from my element getter method:
tell application "SpellAnalysis"
get theseObjects
end tell
8) The result: error "The variable objects is not defined." number -2753 from "objects"
9) Pull my hair out
I thought I should post some addition information on Cocoa Scriptability support for Core-data applications since there is so little information out there. I spent a least a month trying to understand how to come to terms with this mechanism.
Although I was able to provide AppleScript support for my core-data application using index specifiers, I found that employing 'uniqueID' specifiers provided a better fit. Better, because core data to-many relationships are supported by unordered sets, rather then arrays. Core data provides a way for you to specify a managed object by an object ID that can be evaluated by a Cocoa Scriptability method. Nevertheless, to implement support for a "too-many" relation using uniqueID specifiers, additional code elements are needed.
1) Provide a property element in the 'sdef' for each entity you will be supporting. For example, to support my 'level' entity I post the following within the 'levels' class tags:
Note that the type is designated 'text' and not 'specifier'. The 'uniqueID' interchange between the AppleEvent mechanism and Cocoa AppleScript support will be a string value. Also notice that the 'cocoa key' value is 'uniqueID'. This key (typical of such keys in the 'sdef') is used by the AppleScript scriptability support to identify a method name in your application that conforms to a KVC pattern.
2) Post a 'valueInWithUniqueID' method within the class that contains the target objects. It is within this method that you provide a way to extract the managed object corresponding to whatever 'uniqueID' is passed to the method. Here's mine for my 'levelsArray' KVO method posted within my container class, 'Levels'.
And here is my 'sdef' property declaration for the contained 'unit' class:
My 'Units' class also evokes the value method. Note the essential KVC name pattern:
With these in place, if my AppleScript needs to specify a 'level' object from its 'uniqueID', it will be answered. This seems to come into play when you have a hierarchy of entity classes and you write an AppleScript that 1) evokes a command that returns a reference to its result, and 2) acts upon this returned result with another command:
Curiously, the following does not evoke the value method:
Note that it lacks condition 1--a primary command (e.g. 'make') is missing. In this case, the implied AppleScript 'get' command is evoked, however Cocoa scriptability seems to determine the values of the entity hierarchy by another means.
3) Provide 'uniqueID' object specifiers for all objects returned from commands that you support, as well as explicitly named 'objectSpecifier' for each of entity sub-classes that support their implied 'get' commands. For example, my 'clone' command, posted within its 'performDefaultImplementation' provides the following method:
Depending on whether you are manipulating a single object or a range of objects with your command, you return the 'uniqueIDSpecifier' directly or add it to an array of consecutive such specifiers that are returned after the last addition. To support the implied 'get' command, you post a 'uniqueID' object specifier in each of your managed object entity sub-classes. The following specifier supports my 'Unit' class sub-class:
Note the second commented line indicate that I post the results of this specifier in a global variable so that the object specifier of contained classes can use this specifier result as its container specifier. The application delegate is the one place all entity sub-classes can have access to application-wide accessors and methods such as this object specifier result.
I do hope this helps someone out there like myself, last month.