Re: Script commands and the application object
Re: Script commands and the application object
- Subject: Re: Script commands and the application object
- From: email@hidden
- Date: Wed, 20 Mar 2002 12:07:57 -0800
Thanks to everyone who has replied, I'm slowly figuring this stuff out.
tell application "Constrictor"
set frame to {100, 100, 128, 128}
end tell
fails in all cases.
Okay, here's my guess:
I bet that the initial -valueForKey: call is being made on 'frameRect'
simply to check whether the result is a single object or an array.
Since you are returning an array, -makeReceiver:takeValue: decides to
use the array method -replaceValueAtIndex:inPropertyWithKey:withValue:
instead of the single-object -takeValue:forKey:.
A small piece of evidence that the scripting key-value coding is built
with mixed single/multiple value support is in this comment in
NSScriptKeyValueCoding.h:
- (id)valueAtIndex:(unsigned)index inPropertyWithKey:(NSString *)key;
// Retrieve a single value from a multi-value key. This actually
works with a single-value key as well if the index is 0.
// The method valueIn<Key>AtIndex: will be used if it exists
So then the implementation of
-replaceValueAtIndex:inPropertyWithKey:withValue: tries to see if
you've implemented -replaceInFrame:atIndex: (see comments in that
header again), sees that you haven't implemented it, and falls back on
its default strategy. It grabs the current array again with
-valueForKey:, in order to stuff the new value into index 0. (As you
suspected.)
The NSInternalScriptError means that during the processing something
raised an NSException. Add a breakpoint to -[NSException raise] to find
out where that is happening. (My guess is somewhere it is attempting to
-insertObject:atIndex: on a non-mutable array, but that's just a guess.)
These guesses seem fairly good to me, and pursuing them got me to a
workaround that might interest others. I implemented
-replaceInFrameRect:atIndex: to check whether the value passed in is an
NSArray; if it is, I just call setFrameRect: with the array and ignore
the index passed to me. Thus I end up setting the key in the way I
think NSSetCommand ought to be doing it in the first place.
After doing this, I saw an interesting thing in gdb: my
-replaceInFrameRect:atIndex: was getting called four times! Each time,
it gets passed the whole four-value NSArray, but the index passed to it
goes 0, 1, 2, 3. Fascinating, eh? *Possibly* even the way it's
supposed to work, but I doubt it, and in any case it isn't documented
worth a bean. I chose to address this by checking the index, and if
it's non-zero and the value is an array, simply ignoring the call. So
only the set to index 0 takes effect, and it sets all four values.
Arguably, I ought to honor all four calls, but only set the value with
the given index, taking it from that index in the array passed in,
setting it to that index in my state. That would mean that the set
would be done in four steps, though, instead of as one atomic action,
which in my case has some negative consequences.
Finally, I needed to implement what I am guessing is the correct
behavior of -replaceInFrameRect:atIndex:, where it gets passed a single
NSNumber as a value. I don't know whether there's even a way to make
that happen from AppleScript, but if there is, my code now supports
it. :->
So the final method I came up with was:
- (void)replaceInFrameRect:(id)value atIndex:(unsigned int)index
{
if ([value isKindOfClass:[NSArray class]])
{
// Work around but in NSSetCommand...
if (index == 0)
[self setFrameRect:value];
}
else if ([value respondsToSelector:@selector(intValue)])
{
int intValue = [value intValue];
if (index == 0) [self setFrameX:intValue];
else if (index == 1) [self setFrameY:intValue];
else if (index == 2) [self setFrameWidth:intValue];
else if (index == 3) [self setFrameHeight:intValue];
else
[NSException raise:NSOperationNotSupportedForKeyException
format:@"index outside [0, 3] set on frameRect attribute of
ConstrictorApp"];
}
else
{
[NSException raise:NSOperationNotSupportedForKeyException
format:@"illegal value set on frameRect attribute of ConstrictorApp"];
}
}
I hope this helps somebody... again, thanks for the helpful pointers,
I think I'll have the scriptability I want finished soon now...
Ben Haller
Stick Software
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.