I’m new to AppleScriptObjC, but not so much AppleScript. In the past, I have had to figure out creative work-arounds for AppleScript being only able to do one task at a time… Unfortunately, I am not having much luck doing this in AppleScriptObjC. What I would like to do seems fairly simple (those are always the hardest, right?)
Here’s what currently happens:
¢ User clicks a button which runs a script on a remote machine
¢ A progress bar for the user appears and continually updates in the UI of my app (repeat loop for 5 mins)
¢ User cannot do anything else in my app until the repeat loop completes
Here’s what I want to happen:
¢ User clicks a button which runs a script on a remote machine
¢ A progress bar for the user appears and continually updates in the UI of my app (repeat loop for 5 mins)
¢ Progress bar runs on a timer, self-updating
¢ User is free to do other things in the app (click more buttons, run other scripts) while the progress bar is updating
Any help, or a nudge in the right direction would be appreciated very much!! Thank you!
script AppDelegate
property parent : class "NSObject"
property progressBar : missing value
on buttonClickedTIMER_(sender)
tell application "Finder" of machine "eppc://username:password@server.local"
open file "Macintosh HD:Path:To:Application.app"
end tell
repeat 300 times ----- I want this part
progressBar's incrementBy_(1) ----- to be executed
delay 1 ----- without "pausing" the app
end repeat ----- Is it possible?
progressBar's stopAnimation_(me) ----- This bit too :)
end buttonClickedTIMER_
on applicationWillFinishLaunching_(aNotification)
-- Do Nothing
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
You can go close by using an NSTimer to update progress bar. But there is a limit, in that there is only one instance of AppleScript for your application, and it can only do one thing at a time. The key is to try to break your actions into smaller actions, or have them periodically check the event queue, so that the timer gets to do its thing.
Here’s the very basic version of what I needed: Clicking a button from the app’s GUI starts a progress bar that runs for a specified time and then stops… and while the progress bar runs, the app doesn’t freeze (using a repeat loop instead of NSTimer caused the app to “lock up” / freeze while the repeat loop ran). Using NSTimer allowed me to do exactly what I wanted.
script AppDelegate
property parent : class "NSObject"
property NSTimer : class "NSTimer"
property progressBar : missing value
property theTimer : missing value
property x : missing value
on startProgressBarButtonClicked_(sender) -- LINKED TO "START" BUTTON IN IB
set x to 60
-- UNHIDE THE PROGRESS BAR:
progressBar's setHidden_(0)
-- CALLS METHOD "startProgressBar_" & STARTS NSTIMER:
set theTimer to current application's NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1, me, "startProgressBar:", "", true)
end startProgressBarButtonClicked_
on startProgressBar_(sender)
-- CONTINUALLY UPDATES PROGRESS BAR:
progressBar's incrementBy_(1)
set x to x-1
if x is 0 then
-- STOP THE NSTIMER, STOP THE PROGRESS BAR ANIMATION, AND HIDE THE PROGRESS BAR:
theTimer's invalidate()
progressBar's stopAnimation_(me)
progressBar's setHidden_(1)
end if
end startProgress_
end script