Sunday, December 17, 2017

#1 2009-09-14 03:06:13 pm

HippoMan
Member
Registered: 2008-09-18
Posts: 114

Invoking an AppleScript handler from within an Objective C method?

I'm in the process of converting one of my AppleScripts to an ASOC application. However, this app is dependent on an idle handler, and it appears that on idle does not work under ASOC.

Therefore, I have written my own version of an idle handler inside of the Objective C environment by means of the performSelector:withObject:afterDelay: method of NSObject. This works, but of course it can only invoke a method that is also written in Objective C.

Now, what I'd like to do is call my on idle handler that was already written in AppleScript from within an Objective C method that I'm invoking by means of my Objective C idle handler. This way, I don't need to re-write all of my AppleScript idle handler code in Objective C.

So this finally brings me to my question: how do I invoke an AppleScript handler from within an Objective C method under ASOC?

Thanks in advance.

Offline

 

#2 2009-09-14 06:39:35 pm

HippoMan
Member
Registered: 2008-09-18
Posts: 114

Re: Invoking an AppleScript handler from within an Objective C method?

Well, I came up with a way to do it. It involves the use of the performSelector: method of NSObject.

Here's an example of how to do it. First, I create a class called Example. Here's its interface file:

#import <Cocoa/Cocoa.h>

@interface Example : NSObject {
    NSObject* obj;
}
+(Example*)init:(NSObject*)xobj;
-(id)invokeHandler:(SEL)xhandler;
@end


And here's its implementation:
#import "Example.h"

@implementation Example

+(Example*)init:(NSObject*)xobj {
    Example* me = [Example alloc];
    if (me != nil) {
        me->obj = xobj;
    }
    return me;
}
-(id)invokeHandler:(SEL)xhandler {
    return [obj performSelector:xhandler];
}
@end


Note that the constructor takes an object, and the invokeHandler: method takes the name of a handler that gets invoked as a method of that object.

And the object we pass to the constructor is simply the me variable from within the AppleScript. Here's the code:

Applescript:

script ExampleAppDelegate
   
   property Example : class "Example" of current application
   
   -- inheritance
   property parent : class "NSObject"
   
   on applicationWillFinishLaunching_(aNotification)
       set ex to Example's init_(me)
       ex's invokeHandler_("testit")
   end applicationWillFinishLaunching_
   
   on applicationShouldTerminate_(sender)
       -- Insert code here to do any housekeeping before your application quits
       return my NSTerminateNow
   end applicationShouldTerminate_
   
   on testit()
       display dialog "It worked!"
   end testit
   
end script

When running this, the "It worked!" dialog box indeed pops up.

I couldn't get this to invoke the standard idle handler, but that's not a big deal. I could always create an idlewrapper() handler which simply calls idle, and then call idlewrapper using this methodology.

I don't know if this is the best way to implement this functionality. Any thoughts?

Last edited by HippoMan (2009-09-14 06:43:13 pm)

Offline

 

#3 2009-09-15 01:06:07 am

mark hunte
Member
From:: Hello, London Calling
Registered: 2006-03-20
Posts: 1030
Website

Re: Invoking an AppleScript handler from within an Objective C method?

Not sure if this thread is any help

How to provide idle time in Cocoa/Objective-C?


Tap,tap,tap , hello , testing 1..2,  1...2,
http://www.markosx.com/thecocoaquest/

Offline

 

#4 2009-09-15 10:03:36 am

HippoMan
Member
Registered: 2008-09-18
Posts: 114

Re: Invoking an AppleScript handler from within an Objective C method?

Thanks for your reply.

Yes, now that I know how to cause an AppleScript handler to be fired off from within the Objective C environment, I can use the approaches outlined in the discussion you mentioned, among others, to create an idle handler in that language, and then to use the performSelector: method of NSObject to invoke that AppleScript handler, as I describe above.

Since there is also a performSelector:withObject:afterDelay: method, that one seems to be the most straightforward way to do this, although perhaps there are pitfalls to this that I'm not aware of (I'm fairly new to all this). However, I tried it this way, and it seems to work, at least in the simple case in which I'm using it.

I describe that appoach here: http://macscripter.net/viewtopic.php?id=30480

I can always change this to use one of the other delay-repeat approaches that are outined in the discussion that you pointed me to and elsewhere, if performSelector:withObject:afterDelay: turns out to have any drawbacks.

Last edited by HippoMan (2009-09-15 10:46:43 am)

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)