Getting objectSpecifier right...

  • I'm getting the classic '«class » id 2 of document "Untitled"'
    response trying to get a reference to an object within my document via
    AppleScript.

    The object in question is a member of a subclass of the class that has
    the objectSpecifier method (pasted below) which is returning the
    result.

    A couple of notes:

    - I am trying to build an object specifier that identifies the object
    by unique id within the document; specifying by index would be
    difficult, and slow if I have to enumerate all objects of the class
    (I'm anticipating thousands in normal usage).

    - I'm fuzzy on what the "class description" argument should be for
    initWithContainerClassDescription. I assume it should be the class
    description for the object itself; I tried using both the result of
    classDescriptionForClass (commented out below), and digging out of the
    suite registry.  But I'm guessing based on various samples I have
    studied.

    Any thoughts?

    TIA,
    Doug K;

    - (NSScriptObjectSpecifier *)objectSpecifier
    {
    NSLog( @"Category: objectSpecifier requested for %@", [self
    recordDescription] );
    // try to specify the category by id
    NSScriptObjectSpecifier *containerRef = [[self repository]
    objectSpecifier];
    // NSScriptClassDescription *classDesc = (NSScriptClassDescription
    *)[NSScriptClassDescription classDescriptionForClass:[Category class]];
    NSScriptSuiteRegistry *reg = [NSScriptSuiteRegistry
    sharedScriptSuiteRegistry];
    NSDictionary *classes = [reg classDescriptionsInSuite:@"Prospector"];
    NSScriptClassDescription *classDesc = [classes
    objectForKey:@"Category"];
    NSLog( @"...found category description %@", classDesc );
    NSNumber *myID = [[NSNumber alloc] initWithLong:[self recordID]];
    NSUniqueIDSpecifier *spec = [[NSUniqueIDSpecifier alloc]
    initWithContainerClassDescription:classDesc
                      containerSpecifier:containerRef
                                                                                             key:@"recordID"
                                                                                         uniqueID:myID];
    return spec;
    }
  • On 9 Oct, 2004, at 1:13 PM, Doug Knowles wrote:

    > I'm getting the classic '«class » id 2 of document "Untitled"'
    > response trying to get a reference to an object within my document via
    > AppleScript.
    >
    > The object in question is a member of a subclass of the class that has
    > the objectSpecifier method (pasted below) which is returning the
    > result.

    Right. Gotcha.

    > A couple of notes:
    >
    > - I am trying to build an object specifier that identifies the object
    > by unique id within the document; specifying by index would be
    > difficult, and slow if I have to enumerate all objects of the class
    > (I'm anticipating thousands in normal usage).
    >
    > - I'm fuzzy on what the "class description" argument should be for
    > initWithContainerClassDescription. I assume it should be the class
    > description for the object itself; I tried using both the result of
    > classDescriptionForClass (commented out below), and digging out of the
    > suite registry.  But I'm guessing based on various samples I have
    > studied.

    Actually, no. It should be the class description for the container. The
    easiest way to get this is to call (NSScriptClassDescription *) [[self
    repository] classDescription], assuming I read your code right. There
    is no need to check with the suite registry.

    I wrote a guide for supporting AppleScript with Cocoa—the most complete
    I've seen—at <http://cocoadev.com/?HowToSupportAppleScript>. If you
    haven't checked it out already, you should.

    > - (NSScriptObjectSpecifier *)objectSpecifier
    > {
    > NSLog( @"Category: objectSpecifier requested for %@", [self
    > recordDescription] );
    > // try to specify the category by id
    > NSScriptObjectSpecifier *containerRef = [[self repository]
    > objectSpecifier];
    > //    NSScriptClassDescription *classDesc = (NSScriptClassDescription
    > *)[NSScriptClassDescription classDescriptionForClass:[Category
    > class]];
    > NSScriptSuiteRegistry *reg = [NSScriptSuiteRegistry
    > sharedScriptSuiteRegistry];
    > NSDictionary *classes = [reg classDescriptionsInSuite:@"Prospector"];
    > NSScriptClassDescription *classDesc = [classes
    > objectForKey:@"Category"];
    > NSLog( @"...found category description %@", classDesc );
    > NSNumber *myID = [[NSNumber alloc] initWithLong:[self recordID]];
    > NSUniqueIDSpecifier *spec = [[NSUniqueIDSpecifier alloc]
    > initWithContainerClassDescription:classDesc
    > containerSpecifier:containerRef key:@"recordID" uniqueID:myID];
    > return spec;
    > }
  • On Oct 9, 2004, at 4:13 PM, Doug Knowles wrote:

    > - (NSScriptObjectSpecifier *)objectSpecifier
    > {
    > NSLog( @"Category: objectSpecifier requested for %@", [self
    > recordDescription] );
    > // try to specify the category by id
    > NSScriptObjectSpecifier *containerRef = [[self repository]
    > objectSpecifier];
    > //    NSScriptClassDescription *classDesc = (NSScriptClassDescription
    > *)[NSScriptClassDescription classDescriptionForClass:[Category
    > class]];
    > NSScriptSuiteRegistry *reg = [NSScriptSuiteRegistry
    > sharedScriptSuiteRegistry];
    > NSDictionary *classes = [reg classDescriptionsInSuite:@"Prospector"];
    > NSScriptClassDescription *classDesc = [classes
    > objectForKey:@"Category"];
    > NSLog( @"...found category description %@", classDesc );
    > NSNumber *myID = [[NSNumber alloc] initWithLong:[self recordID]];
    > NSUniqueIDSpecifier *spec = [[NSUniqueIDSpecifier alloc]
    > initWithContainerClassDescription:classDesc
    > containerSpecifier:containerRef
    > key:@"recordID"
    > uniqueID:myID];
    > return spec;
    > }

    Dustin answered the question asked. I'd also point out that the above
    code leaks both myID and spec.

    Jim
  • Dustin Voss wrote:

    > Actually, no. It should be the class description for the container. The
    > easiest way to get this is to call (NSScriptClassDescription *) [[self
    > repository] classDescription], assuming I read your code right. There
    > is no need to check with the suite registry.

    I have changed this per your advice, with no change to the results.

    Here's more observations:

    - The class I'm having trouble with is the target of several "to-many"
    relationships; i.e., network of  "category" classes that refer to each
    other through various to-many relationships.  As a consequence, my
    "element" descriptions need to refer to the relationship by names other
    than the type of the class, such as "children", "parents", etc.  So I
    describe the relationship as:

    <element type="child" access="r" description="Child(ren) in category
    hierarchy" >
      <cocoa method="childCategories"/>
    </element>

    ...which forces me to create a type for the reference:

    <class name="child" plural="children" code="chld"
    description="Child(ren) of a category" inherits="category">
      <cocoa class="Category"/>
    </class>

    The sdef compiler passes this through by defining "child" as a synonym
    for "category".  I don't know if this has a bearing on what I pass for
    a key in the category's object specifier.

    - A typical descriptor generated by my method seems to have a bad
    specification of the key, as shown by the debug output below (note the
    "want:0x00000000"):

    Result: <NSAppleEventDescriptor: [ obj { from:obj { from:obj {
    from:'null'(), want:'docu', form:'name',
    seld:utxt($0055006E007400690074006C00650064$) }, want:'prop',
    form:'prop', seld:'rorg' }, want:0x00000000, form:'indx', seld:1 } ]

    {«class » 1 of root organizer of document "Untitled" of application
    "Prospector"}

    >
    > I wrote a guide for supporting AppleScript with Cocoa - the most
    > complete
    > I've seen - at <http://cocoadev.com/?HowToSupportAppleScript>. If you
    > haven't checked it out already, you should.
    >

    I have had that page open on my desktop for days now; it has been very
    helpful to get me this far.  Thanks!
  • On 10 Oct, 2004, at 5:21 PM, Doug Knowles wrote:

    > Dustin Voss wrote:
    >
    >> Actually, no. It should be the class description for the container.
    >> The
    >> easiest way to get this is to call (NSScriptClassDescription *) [[self
    >> repository] classDescription], assuming I read your code right. There
    >> is no need to check with the suite registry.
    >
    > I have changed this per your advice, with no change to the results.
    >
    > Here's more observations:
    >
    > - The class I'm having trouble with is the target of several "to-many"
    > relationships; i.e., network of  "category" classes that refer to each
    > other through various to-many relationships.  As a consequence, my
    > "element" descriptions need to refer to the relationship by names
    > other than the type of the class, such as "children", "parents", etc.
    > So I describe the relationship as:
    >
    > <element type="child" access="r" description="Child(ren) in category
    > hierarchy" >
    > <cocoa method="childCategories"/>
    > </element>
    >
    > ...which forces me to create a type for the reference:
    >
    > <class name="child" plural="children" code="chld"
    > description="Child(ren) of a category" inherits="category">
    > <cocoa class="Category"/>
    > </class>

    I think this is a limitation of sdef files. In truth, the element name
    ought to be "children", but the class should be "category". You can
    manually adjust the .scriptSuite or .scriptTerminology files, but I
    think there is a better work-around.

    There is no rule in AppleScript that says that elements have to be a
    particular class. In fact, if you look at TN 2016 (at
    http://developer.apple.com/technotes/tn2002/tn2106.html) there is an
    example of how a "duck" element can return "mallard", etc.

    You should be able to use this to your advantage. Just create empty
    <class> declarations for "child", "parent", etc., with no inheritance
    information. These will be placeholders, with no Cocoa equivalent. In
    the appropriate Cocoa accessor methods, return a "category" object
    instead of "child" or "parent" or whatever.

    Of course, one thing you have to look out for is the object specifier.
    The "category" objects can't return themselves as "child x of whatever"
    or "parent y of whatever"; you'd have to return them as "category z of
    categories" or something. I think you've done this already.

    >> I wrote a guide for supporting AppleScript with Cocoa - the most
    >> complete
    >> I've seen - at <http://cocoadev.com/?HowToSupportAppleScript>. If you
    >> haven't checked it out already, you should.
    >
    > I have had that page open on my desktop for days now; it has been very
    > helpful to get me this far.  Thanks!

    I'm glad it's helped, and you're welcome.
previous month october 2004 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Go to today