I have a rather long AppleScript that I’ve converted to a AppleScript Obj-C app using Xcode 10. The only interface object is a push button that starts the script. It runs fine, but I’d like to add a Indeterminate Circular Progress Indicator to show that the script is processing – so users do not click the button any additional times until the script has completed with it’s current task. Ideally, it might be helpful if I disabled the push button while the Indeterminate Circular Progress Indicator is actively spinning. I’m new to Xcode, so my knowledge of Xcode is very limited. Binding the “Start” button to the delegate is the only thing I seem to get working. What additional steps would be needed to add a Determinate Bar Progress Indicator in Xcode?
I noted there are similar and outdated post. I’ve reviewed many of them, but still need guidance.
Example:
on startScript_(sender)
-- Additional task code would go here.
end startScript_
Mac OS 10.13.6
AppleScript Version 2.7
Xcode Version 10.1 (10B61)
You may not realise it, but what you’re asking for is effectively how to write an Xcode-based AppleScriptObjC app, and that’s not something easily answered in a single reply. To make it more complicated, there’s more than one way to do what you want.
here’s one approach. To start, add a progress indicator to your window, and make a property that is an outlet to it – one that has an initial value of missing value, and that you link by control-clicking on the progress indicator and choosing the property as a referencing outlet.
Your code should look something like this:
property progIndicator : missing value
on startScript:sender
sender's setEnabled:false
progIndicator's startAnimation:me
my performSelector:"continueScript:" withObject:me afterDelay:0.1
end startScript:
on continueScript:sender
-- do your stuff here
sender's setEnabled:true
progIndicator's stopAnimation:me
end continueScript:
That will get you started, although you may still see the spinning beach ball if your script takes a long time. You can find the solution to that, which is a bit more complicated, by searching here.
I tried your suggestion and didn’t have any luck. I am not able to link MainMenu.xib’s progress indicator icon to the progIndicator property. I’ve included a couple screen shots below.
AppDelegate.applescript:
[code]use AppleScript version “2.4” – Yosemite (10.10) or later
use framework “Foundation”
use scripting additions
script AppDelegate
property parent : class “NSObject”
-- IBOutlets
property theWindow : missing value
property progIndicator : missing value
on startScript:sender
sender's setEnabled:false
progIndicator's startAnimation:me
my performSelector:"continueScript:" withObject:me afterDelay:0.1
end startScript:
on continueScript:sender
-- do your stuff here -- START
-- EXAMPLE CODE:
set My_List to {"1", "2", "3"} as list
repeat with i in My_List
display dialog i giving up after 1
end repeat
-- do your stuff here -- END
sender's setEnabled:true
progIndicator's stopAnimation:me
end continueScript:
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script[/code]
Also, I have 2 questions regarding your initial reply.
1.
Your syntax is a bit different than what I originally used. Are they equivalent? I tried both ways.
My Code: on startScript_(sender) Your Code: on startScript:sender
2.
You said:
“…which is a bit more complicated, by searching here”. By “here”, did you mean in the AppleScriptObjC and Xcode forum? It almost sounded like you meant to include a URL link.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
script AppDelegate
property parent : class "NSObject"
-- IBOutlets
property theWindow : missing value
property progIndicator : missing value
on startScript:sender
sender's setEnabled:false
progIndicator's startAnimation:me
my performSelector:"continueScript:" withObject:me afterDelay:0.1
end startScript:
on continueScript:sender
-- do your stuff here -- START
-- EXAMPLE CODE:
set My_List to {"1", "2", "3"} as list
repeat with i in My_List
display dialog i giving up after 1
end repeat
-- do your stuff here -- END
sender's setEnabled:true
progIndicator's stopAnimation:me
end continueScript:
on applicationWillFinishLaunching:aNotification
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching:
on applicationShouldTerminate:sender
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate:
end script
They don’t appear. Hold down the control key and click and drag from the indicator to File’s Owner at the top-left; choose the property name from the list that appears.
They the same – the colon-delimited version was introduced in macOS 10.10. Open and compile in a script editor, and you will see.
Shane, I can’t express how much I appreciate your help! I finally was able to get it to work. As you noted, the progress indicator does continue to spin after the script completes, but I’ll search the forum for solutions as you noted. I’ll post the complete solution when I have it.
I did know that I needed to old down the control key and drag to link the interface. I had been clicking and dragging from the indicator, just as I had done for the button object. What actually worked, was clicking and dragging from the App Delegate to the Progress Indicator and then selecting the outlet. It is directionally specific!
It is insane that doing such simple things have been made so difficult. I love to hate AppleScript for the same reason. Apple has spent resources engineering all of this technology into their products, only to let it languish in the dark. I spent countless hours over a week searching the web to do this one simple thing!
The script almost does what I want, except when the app launches, it shows the progress indicator on the initial app window.
I’ve attached a screen video that shows the app run through two cycles. The 1st starts from the initial screen as it appears upon launch. The second cycle shows how I’d like the app to work – no progress indicator until the button is clicked.
I tried many iterations with various code. Examples include: displayedWhenStopped, theWindow’s update_(), various progIndicator’s setHidden: and various handlers in an attempt to hide the progress indicator before the initial app screen displays.
In my initial post, I suggested disabling the button once it was pressed, but that isn’t needed since you cannot click the button while the progress indicator animates.
I’ve had no luck, and don’t have a clue how to proceed. Any suggestions?
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
script AppDelegate
property parent : class "NSObject"
-- IBOutlets
property theWindow : missing value
property progIndicator : missing value
property setSpinnerHidden : missing value
on startScript:sender
progIndicator's setHidden:1
my performSelector:"continueScript:" withObject:me afterDelay:0.3
end startScript:
on continueScript:sender
-- SHOW progIndicator
progIndicator's setHidden:0
progIndicator's startAnimation:me
-- do your stuff here -- START
-- EXAMPLE CODE:
set My_List to {"1", "2", "3"} as list
repeat with i in My_List
display dialog i giving up after 1
end repeat
-- do your stuff here -- END
-- HIDE progIndicator
progIndicator's setHidden:1
progIndicator's stopAnimation:me
end continueScript:
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
I’m not sure what is going on with the links. I’ve used the tags as directed on the help page: [url=/help.php#img]https://macscripter.net/help.php#img[/url]. They show as missing images in Safari, but you can still view them by holding down the Control key and choosing New Tab or New Window.
As you noted, no tags are shown at all with Firefox! The links are in Dropbox. I’ll repost below with and without tags as well as a different host. (After testing the Preview, it seems the issue is with Dropbox URLs.)
I had previously reviewed the thread @ https://macscripter.net/viewtopic.php?id=46038
and tried both tickleQueue() and fordEvent(). They didn’t seem to work, but it’s possible I did not implement them correctly. It’s hard to say, as I have tried so many things.
Just to reiterate, I’d like to remove the spinner image that appears when the app launches. It currently shows, then is hidden after the 1st click of the button and thereafter properly animates only after a button click.
I ended up with a script that does what I want, albeit a stalling progress wheel. I also added a text string to the interface which could be used to provide text updates as the app does it’s processing. The actual script processes files in iTunes which seems to cause the progress wheel to stall. I tried many ways to force the animation to play smoothly, but without any success. Thank you to all who post and support this blog.
Movie of Demo Script App:
script AppDelegate
property parent : class "NSObject"
-- IBOutlets
property theWindow : missing value
property doProcess : missing value
property enableDoProcess : missing value
property iterateItems : missing value
property Txt_Display : missing value
property Txt_List : missing value
property appLaunch : missing value
property animateSpinner : missing value
property setSpinnerHidden : missing value
property myImage : missing value
on doProcess:sender
my performSelector:"animateSpinner" withObject:me
tell appLaunch to setStringValue:"Loading Resources..."
my performSelector:"iterateItems:" withObject:me afterDelay:0.1
sender's setEnabled:false
end doProcess:
on iterateItems:sender
setSpinnerHidden's setHidden:0
animateSpinner's startAnimation:me
set My_Counter to 0
delay 1
set Txt_List to {"I Say Hello", "You say Goodbye", "Hello, Hello", "Goodbye, Goodbye", ""}
repeat with i in Txt_List
set Txt_Display to i as string
tell appLaunch to setStringValue:Txt_Display
delay 1
end repeat
setSpinnerHidden's setHidden:1
animateSpinner's stopAnimation:me
enableDoProcess's setEnabled:true
end iterateItems:
on applicationWillFinishLaunching:aNotification
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching:
on applicationShouldTerminate:sender
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate:
end script