• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSAppleScript not in the main thread
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSAppleScript not in the main thread


  • Subject: Re: NSAppleScript not in the main thread
  • From: Kirk Kerekes <email@hidden>
  • Date: Mon, 22 May 2006 12:07:51 -0500

Appended is a simplistic-but-effective workaround for the requirement that NSAppleScript execute on the main thread.

The method-of-interest is:

- (NSAppleEventDescriptor *) executeOnMainThreadReturningError: (NSDictionary **) error;

-- which is modeled on the existing:

- (NSAppleEventDescriptor *)executeAndReturnError:(NSDictionary **) errorInfo;

-- making this solution an easy drop-in.

This solution is appropriate when the goal is not expressly to run the script in a subthread, but simply to allow a subthread to use the script _as_if_ it could run in the subthread. I have found that because of the event-synchronized scheduling of events run by performSelectorOnMainThread:withObject:waitUntilDone:, the execution of reasonably small AppleScripts by this method rarely causes any serious disruption in user experience. In some cases even fairly large scripts can be broken down into manageable sub-scripts that can be executed serially.

If you are using AppleScript to do something irreducibly time- consuming, you probably want to look elsewhere.

In this solution, the executeOnMainThreadReturningError: method simply executes the script on the main thread using performSelectorOnMainThread:withObject:waitUntilDone: and then returns the resulting NSAppleEventDescriptor and error dictionary.

This is not a universal solution -- no support for separately compiling the script _from_ the subthread is provided. It is assumed that the script has either been precompiled on the main thread, or will be compiled at execution.

It seems to cover the majority of real-world cases, however -- if you have a totally "canned" script, it is trivial to precompile it on the main thread, and if you don't, you are probably recreating the script from scratch with each execution. Compiling from a subthread could easily be added, using the current code as a model.

This could probably be implemented as a category on NSAppleScript by using a NSMutableDictionary as the object for performSelectorOnMainThread:withObject:waitUntilDone:, but when I implemented this I chose the subclass route.


@interface KKNSAppleScript: NSAppleScript { NSAppleEventDescriptor * _resultDescriptor; NSDictionary * _errorDict; }

- (NSAppleEventDescriptor*)resultDescriptor;
- (void)setResultDescriptor:(NSAppleEventDescriptor*)inResultDescriptor;

- (NSDictionary*)errorDict;
- (void)setErrorDict:(NSDictionary*)inErrorDict;

- (NSAppleEventDescriptor *) executeOnMainThreadReturningError: (NSDictionary **) error;

@end

@implementation KKNSAppleScript

- (NSAppleEventDescriptor*)resultDescriptor
{
    return _resultDescriptor;
}

- (void)setResultDescriptor:(NSAppleEventDescriptor*)inResultDescriptor
{
    if (_resultDescriptor != inResultDescriptor) {
        [_resultDescriptor release];
        _resultDescriptor = [inResultDescriptor retain];
    }
}

- (NSDictionary*)errorDict
{
    return _errorDict;
}

- (void)setErrorDict:(NSDictionary*)inErrorDict
{
    if (_errorDict != inErrorDict) {
        [_errorDict release];
        _errorDict = [inErrorDict retain];
    }
}

- (void) dealloc
{
	[self setResultDescriptor: nil];
	[self setErrorDict: nil];
	[super dealloc];
}

- (void) mainThreadExecute:(id) ignored
{
	NEWPOOL(pool);
	NSDictionary * error = nil;
	NSAppleEventDescriptor * aed = [self executeAndReturnError: &error];
	[self setErrorDict: error];
	[self setResultDescriptor: aed];
	CLOSEPOOL(pool);
}

- (NSAppleEventDescriptor *) executeOnMainThreadReturningError: (NSDictionary **) error
{
id temp;
[self performSelectorOnMainThread: @selector(mainThreadExecute:) withObject: self waitUntilDone: YES];
*error = [[[self errorDict] retain] autorelease];
temp = [[[self resultDescriptor] retain] autorelease];
[self setResultDescriptor: nil];
[self setErrorDict: nil];
return temp;
}


@end

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Prev by Date: Re: Cocoa-dev Digest, Vol 3, Issue 681
  • Next by Date: Re: Any source of Printed & Bound docs
  • Previous by thread: Re: NSAppleScript not in the main thread
  • Next by thread: KVO: programmatically created custom views not getting initial value notifications
  • Index(es):
    • Date
    • Thread