How to stop function while it is running

I am coding Mac App on Xcode with Applescript. I made a function that doesn't stop forever, but I can't stop it. It starts when I push a button that is located on the window. Because this function doesn't stop, the button appears pushed forever. And I have to force quit with 'Command+Option+Escape'. (Even if you do this activity, this app may not be stop.) I want release the button before the function starts, and I want to stop this function safely with pushing another button. This is my example. To stop this, push the "Stop" button on Xcode.

property parent : class "NSObject"
property mylabel : missing value

on applicationWillFinishLaunching_(aNotification)
    -- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_

on myStartButtonHandler_(sender)
    my myForeverFunction()
end myStartButtonHandler_

on myStopButtonHandler_(sender)
    --How can I stop "myForeverFunction"?
end myStopButtonHandler_

on myForeverFunction()
    set a to 0
    repeat 100 times
        set a to a+1
        mylabel's setStringValue_(a)
        delay 1
    end repeat
end myForeverFunction

on applicationShouldTerminate_(sender)
    -- Insert code here to do any housekeeping before your application quits 
return current application's NSTerminateNow
end applicationShouldTerminate_

This is the project file --> https://dl.dropboxusercontent.com/u/97497395/test.zip Sorry I am Japanese, I can't write English very well.

Answers


Basically the interface of your application is controlled and updated on your apps main thread. Therefore if you run some code which ties up the main thread then your interface will not have a chance to update itself until the code is complete. So to fix that you run the code in a background thread and thus your interface will be able to update itself.

I don't know if you can do this in AppleScriptObjC because I'm not too familiar with it. Here's how I do it in objective-c. I create a handler (someHandler) and then run this code. Note that since this handler isn't run in the main thread which has an automatically generated release pool, you will have to create and drain a release pool in your handler.

[NSThread detachNewThreadSelector:@selector(someHandler) toTarget:self withObject:nil];

EDIT: Here's the autorelease pool you asked about. In a reference-counted environment do it this way...

-(void)someHandler {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // do your stuff here

    [pool drain];
}

With Automatic Reference Counting (ARC) you would do it this way...

-(void)someHandler {
    @autoreleasepool {
        // do your stuff here
    }
}

So I'm not sure which applies to AppleScriptObjC. A quick google search turned up this post.


Right now your code is looping and looping and important things like the interface are never getting updated. If you call a doEventFetch function to run all of the queued processes, that should fix your problem. Just call it once every loop:

on doEventFetch()
    repeat
        tell current application's NSApp to set theEvent to nextEventMatchingMask_untilDate_inMode_dequeue_(((current application's NSLeftMouseDownMask) as integer) + ((current application's NSKeyDownMask) as integer), missing value, current application's NSEventTrackingRunLoopMode, true)
        if theEvent is missing value then
            exit repeat
        else
            tell current application's NSApp to sendEvent_(theEvent)
        end if
    end repeat
end doEventFetch

on loopFunc()
    repeat
        #Repeat stuff here...
        doEventFetch()
    end repeat
end loopFunc

Need Your Help


About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.